Analog modules reading and pump set speed implemented (untested)

This commit is contained in:
VineetaGupta 2025-03-27 13:40:30 +01:00
parent 200cdc48c7
commit 7ccde7933f
25 changed files with 1519 additions and 1091 deletions

View File

@ -71,6 +71,8 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/scheduler}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/log}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/nms-hal}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/nms_hal}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/nms_can}&quot;"/>
</option>
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.input.1637079955" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.input"/>
</tool>
@ -126,6 +128,8 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/scheduler}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/log}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/nms-hal}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/nms_hal}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/nms_can}&quot;"/>
</option>
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c.197736294" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c"/>
</tool>
@ -159,7 +163,8 @@
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="coappl"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="common"/>
<entry excluding="lss.c|lss.h" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="nehemis"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="nms-hal"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="nms_can"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="nms_hal"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="scheduler"/>
</sourceEntries>
</configuration>
@ -233,6 +238,8 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/scheduler}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/log}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/nms-hal}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/nms_hal}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/nms_can}&quot;"/>
</option>
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.input.957070642" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.input"/>
</tool>
@ -287,6 +294,8 @@
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/scheduler}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/log}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/nms-hal}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/nms_hal}&quot;"/>
<listOptionValue builtIn="false" value="&quot;${workspace_loc:/${ProjName}/nms_can}&quot;"/>
</option>
<inputType id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c.1211672677" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.c.compiler.input.c"/>
</tool>
@ -313,10 +322,10 @@
</toolChain>
</folderInfo>
<sourceEntries>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="nms_hal"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="nehemis"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Core"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="Drivers"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="nehemis"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="nms-hal"/>
</sourceEntries>
</configuration>
</storageModule>

View File

@ -40,11 +40,25 @@
<type>2</type>
<locationURI>copy_PARENT/common</locationURI>
</link>
<link>
<name>nms_can</name>
<type>2</type>
<locationURI>PROJECT_LOC/nms_can</locationURI>
</link>
<link>
<name>nms_hal</name>
<type>2</type>
<locationURI>copy_PROJECT_LOC/nms_hal</locationURI>
</link>
</linkedResources>
<variableList>
<variable>
<name>copy_PARENT</name>
<value>$%7BPARENT-3-PROJECT_LOC%7D/Documents/NorthStar-Endurance-TestBench</value>
</variable>
<variable>
<name>copy_PROJECT_LOC</name>
<value>$%7BPARENT-1-copy_PARENT%7D/NorthStar-Production-Unit-Board-Firmware/ProcessBoardV1</value>
</variable>
</variableList>
</projectDescription>

View File

@ -51,13 +51,13 @@ void MX_ADC1_Init(void)
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{

View File

@ -78,7 +78,7 @@ int main(void)
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
HAL_Init();
/* USER CODE BEGIN Init */

View File

@ -1,9 +1,11 @@
#MicroXplorer Configuration settings - do not modify
ADC1.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_1
ADC1.CommonPathInternal=null|null|null|null
ADC1.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,OffsetNumber-0\#ChannelRegularConversion,NbrOfConversionFlag,master,CommonPathInternal
ADC1.ContinuousConvMode=ENABLE
ADC1.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,OffsetNumber-0\#ChannelRegularConversion,NbrOfConversionFlag,master,Overrun,ContinuousConvMode,CommonPathInternal
ADC1.NbrOfConversionFlag=1
ADC1.OffsetNumber-0\#ChannelRegularConversion=ADC_OFFSET_NONE
ADC1.Overrun=ADC_OVR_DATA_OVERWRITTEN
ADC1.Rank-0\#ChannelRegularConversion=1
ADC1.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_2CYCLES_5
ADC1.master=1
@ -206,8 +208,8 @@ ProjectManager.MainLocation=Core/Src
ProjectManager.NoMain=false
ProjectManager.PreviousToolchain=STM32CubeIDE
ProjectManager.ProjectBuild=false
ProjectManager.ProjectFileName=ProcessBoardV1.ioc
ProjectManager.ProjectName=ProcessBoardV1
ProjectManager.ProjectFileName=EnduranceTestBench.ioc
ProjectManager.ProjectName=EnduranceTestBench
ProjectManager.ProjectStructure=
ProjectManager.RegisterCallBack=
ProjectManager.StackSize=0x400

View File

@ -0,0 +1,92 @@
/**
* @file analogMeasurement.c
*
* @copyright Nehemis SARL reserves all rights even in the event of industrial
* property rights. We reserve all rights of disposal such as
* copying and passing on to third parties.
*
* @brief Source code for ADC data reading module.
*/
/******************************************************************************
* Include Header Files
******************************************************************************/
#include "analogMeasurement.h"
#include "hal_adc.h"
/******************************************************************************
* Macro Constant Declarations
******************************************************************************/
#define ADC_BUFFER_SIZE 9u
/******************************************************************************
* Module Global Variable Declarations
******************************************************************************/
static uint16 adcBuffer_u32[ADC_BUFFER_SIZE];
/******************************************************************************
* Private Function Declarations
******************************************************************************/
static void AnalogMeasurementInitBuffer(void);
/******************************************************************************
* Function Definitions
******************************************************************************/
void AnalogMeasurementInit(void)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
AnalogMeasurementInitBuffer();
HalAdcCalibrate(MAP_HAL_ADC_1);
error_u32 = HalAdcStartDMA(MAP_HAL_ADC_1, (uint32 *)adcBuffer_u32, ADC_BUFFER_SIZE);
if (error_u32 != NMS_ERR_NONE)
{
/* Handle the error (DMA start failed) */
}
}
void AnalogMesaurementRun(void)
{
HalAdcStartDMA(MAP_HAL_ADC_1, (uint32 *)adcBuffer_u32, sizeof(adcBuffer_u32));
}
void AnalogMeasurementReadData(uint32 channel_u32, uint32 *adcValue_pu32)
{
if (adcValue_pu32 == NULL)
{
return; /* Prevent dereferencing NULL pointer */
}
__disable_irq();
switch (channel_u32)
{
case PS1_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[0]; break;
case PS2_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[1]; break;
case PS3_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[2]; break;
case PS4_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[3]; break;
case PMP_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[4]; break;
case FM1_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[5]; break;
case FM2_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[6]; break;
case FM3_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[7]; break;
case FM4_ADC_CHANNEL: *adcValue_pu32 = adcBuffer_u32[8]; break;
default: *adcValue_pu32 = 0uL; break;
}
__enable_irq();
}
/******************************************************************************
* Private Function Definitions
******************************************************************************/
/* @brief Initialize buffer with default values*/
static void AnalogMeasurementInitBuffer(void)
{
for (uint8 i_u8 = 0u; i_u8 < ADC_BUFFER_SIZE; i_u8++)
{
adcBuffer_u32[i_u8] = 0uL;
}
}

View File

@ -0,0 +1,53 @@
/**
* @file analogMeasurement.h
*
* @copyright Nehemis SARL reserves all rights even in the event of industrial
* property rights. We reserve all rights of disposal such as
* copying and passing on to third parties.
*
* @brief ADC measurement module interface.
* This file provides function declarations and necessary definitions
* for reading analog sensor values using ADC with DMA. It defines
* ADC channel mappings, reference voltage, and resolution to ensure
* consistent data acquisition across multiple modules.
*
*/
#ifndef ANALOGMEASUREMENT_H_
#define ANALOGMEASUREMENT_H_
/******************************************************************************
* Include Header Files
******************************************************************************/
#include "nms_types.h"
/******************************************************************************
* Type declarations
******************************************************************************/
#define PS1_ADC_CHANNEL 1u
#define PS2_ADC_CHANNEL 2u
#define PS3_ADC_CHANNEL 3u
#define PS4_ADC_CHANNEL 4u
#define PMP_ADC_CHANNEL 5u
#define FM1_ADC_CHANNEL 6u
#define FM2_ADC_CHANNEL 7u
#define FM3_ADC_CHANNEL 8u
#define FM4_ADC_CHANNEL 9u
#define ANALOG_MEAS_ADC_REF_VOLTAGE 3.3f
#define ANALOG_MEAS_ADC_RESOLUTION 4095.0f /* 12-bit ADC */
/******************************************************************************
* Extern Function Declarations
******************************************************************************/
/* @brief initialize the ADC, calibrate and Start the ADC in DMA mode */
void AnalogMeasurementInit(void);
void AnalogMesaurementRun(void);
/**
* @brief Reads the latest ADC value for the specified channel.
*
* @param channel_u32 The ADC channel to read from.
* adcValue Pointer to store the retrieved ADC value.
*/
void AnalogMeasurementReadData(uint32 channel_u32, uint32 * adcValue_pu32);
#endif /* ANALOGMEASUREMENT_H_ */

View File

@ -0,0 +1,42 @@
#include "nms_types.h"
extern char string1[];
extern char string2[];
extern OCTET_STRING octet1[];
extern OCTET_STRING octet2[];
extern CO_DOMAIN_PTR pDomain1;
extern CO_DOMAIN_PTR pDomain2;
#ifdef xxx
RET_T sdoServInd(CO_LINE_TYPE, BOOL_T, UNSIGNED8, UNSIGNED16, UNSIGNED8);
RET_T sdoServWrInd(CO_LINE_TYPE, BOOL_T, UNSIGNED8, UNSIGNED16, UNSIGNED8);
RET_T sdoServChkInd(CO_LINE_TYPE, BOOL_T, UNSIGNED8, UNSIGNED16, UNSIGNED8, const UNSIGNED8 *);
void errCtrl(CO_LINE_DECL, UNSIGNED8, CO_ERRCTRL_T, CO_NMT_STATE_T);
RET_T nmtInd(CO_LINE_DECL, BOOL_T, CO_NMT_STATE_T);
void pdoInd(CO_LINE_TYPE, UNSIGNED16);
void pdoRecInd(CO_LINE_TYPE, UNSIGNED16);
void pdoSyncInd(CO_LINE_TYPE, UNSIGNED16);
void syncInd(CO_LINE_TYPE);
void syncFinishedInd(CO_LINE_TYPE);
void ledRedInd(CO_LINE_TYPE, BOOL_T);
void ledGreenInd(CO_LINE_TYPE, BOOL_T);
void canInd(CO_LINE_TYPE, CO_CAN_STATE_T);
void commInd(CO_LINE_TYPE, CO_COMM_STATE_EVENT_T);
void sdoClRd(CO_LINE_TYPE, UNSIGNED8, UNSIGNED16, UNSIGNED8, UNSIGNED32, UNSIGNED32);
void sdoClWr(CO_LINE_TYPE, UNSIGNED8, UNSIGNED16, UNSIGNED8, UNSIGNED32);
void sdoQuInd(CO_LINE_TYPE, void *pData, UNSIGNED32 result);
RET_T emcyInd(CO_LINE_TYPE, UNSIGNED16 errCode, const UNSIGNED8 *addErrorCode);
void emcyConsInd(CO_LINE_TYPE, UNSIGNED8 node, UNSIGNED16 errCode, UNSIGNED8 errorRegister, UNSIGNED8 const *addErrorCode);
void timeInd(CO_LINE_TYPE, CO_TIME_T *pTime);
RET_T storeInd(CO_LINE_DECL, UNSIGNED8 subIndex);
#endif
void sdoClientReadInd(UNSIGNED8 canLine, UNSIGNED8 sdoNr, UNSIGNED16 index,
UNSIGNED8 subIndex, UNSIGNED32 size, UNSIGNED32 result);
void sdoClientWriteInd(UNSIGNED8 canLine, UNSIGNED8 sdoNr,
UNSIGNED16 index, UNSIGNED8 subIndex, UNSIGNED32 result);
uint8 getMyNodeId(CO_LINE_DECL);

View File

@ -13,12 +13,12 @@
* Include Header Files
******************************************************************************/
#include "enduranceTestBench.h"
#include "hal_system.h"
#include "stdlib.h"
/* CANopen includes */
#include <gen_define.h>
#include <co_canopen.h>
#include "hal_system.h"
/******************************************************************************
* Macro constant declarations

View File

@ -14,6 +14,7 @@
******************************************************************************/
#include "nms_types.h"
#include "flowmeter.h"
#include "analogMeasurement.h"
/******************************************************************************
* Type declarations
@ -22,38 +23,34 @@
/******************************************************************************
* Macro Constant Declarations
******************************************************************************/
#define FLOWMETER_ADC_REF_VOLTAGE 3.3f
#define FLOWMETER_ADC_RESOLUTION 4095.0f /* 12-bit ADC */
/******************************************************************************
* Private function Declarations
******************************************************************************/
static float32 FlowmeterReadVoltage(FlowmeterMain_st *flowmeter_pst);
static void FlowmeterReadVoltage(FlowmeterMain_st * flowmeter_pst);
FlowmeterMain_st *flowmeter_gpst;
/******************************************************************************
* Extern Function Definitions
******************************************************************************/
void FlowmeterInit(FlowmeterMain_st *flowmeter_pst, ADC_HandleTypeDef *adcHandle_pst, uint32 channel_u32)
void FlowmeterInit(FlowmeterMain_st *flowmeter_pst)
{
if (flowmeter_pst == NULL || adcHandle_pst == NULL)
if (flowmeter_pst == NULL)
{
/* ERROR */
}
flowmeter_pst->adcHandle_pst = adcHandle_pst;
flowmeter_pst->channel_u32 = channel_u32;
flowmeter_pst->mKu_f32 = 5.0f; // Default value
}
void FlowmeterGetFlow(FlowmeterMain_st *flowmeter_pst)
{
if (flowmeter_pst == NULL)
{
/* ERROR */
}
flowmeter_pst->rawQ_f32 = flowmeter_pst->mKu_f32 * FlowmeterReadVoltage(flowmeter_pst);
FlowmeterReadVoltage(flowmeter_pst);
flowmeter_pst->rawQ_f32 = flowmeter_pst->mKu_f32 * flowmeter_pst->voltage_f32;
}
@ -88,40 +85,11 @@ void FlowmeterSetKu(FlowmeterMain_st *flowmeter_pst, float32 ku_f32)
* @return ADC output voltage based on sensor reading.
*
*/
static float32 FlowmeterReadVoltage(FlowmeterMain_st *flowmeter_pst)
static void FlowmeterReadVoltage(FlowmeterMain_st *flowmeter_pst)
{
uint32 adcVal_u32 = 0uL;
if (flowmeter_pst == NULL || flowmeter_pst->adcHandle_pst == NULL)
{
return 0.0f; /* Error Case */
}
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = flowmeter_pst->channel_u32; /* Set the channel specific to this flowmeter */
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
if (HAL_ADC_ConfigChannel(flowmeter_pst->adcHandle_pst, &sConfig) != HAL_OK)
{
return 0.0f; /* ERROR */
}
/* Start ADC conversion and poll for completion */
if (HAL_ADC_Start(flowmeter_pst->adcHandle_pst) == HAL_OK)
{
if (HAL_ADC_PollForConversion(flowmeter_pst->adcHandle_pst, HAL_MAX_DELAY) == HAL_OK)
{
adcVal_u32 = HAL_ADC_GetValue(flowmeter_pst->adcHandle_pst);
}
HAL_ADC_Stop(flowmeter_pst->adcHandle_pst);
}
else
{
/* ERROR */
}
/* Convert ADC value to voltage (assuming 12-bit resolution and 3.3V reference) */
float32 voltage_f32 = (float)adcVal_u32 * (FLOWMETER_ADC_REF_VOLTAGE / FLOWMETER_ADC_RESOLUTION);
uint32 adcVal_u32 = 0uL;
AnalogMeasurementReadData(flowmeter_pst->channel_u32, &adcVal_u32);
return voltage_f32;
flowmeter_pst->voltage_f32 = (float32)adcVal_u32 * (ANALOG_MEAS_ADC_REF_VOLTAGE / ANALOG_MEAS_ADC_RESOLUTION);
}

View File

@ -22,19 +22,16 @@
******************************************************************************/
typedef struct
{
ADC_HandleTypeDef *adcHandle_pst;
float32 mKu_f32;
uint32 channel_u32;
float32 rawQ_f32;
float32 voltage_f32;
} FlowmeterMain_st; /* HubaFlowmeter structure definition */
/******************************************************************************
* Macro Constant Declarations
******************************************************************************/
#define FLOWMETER_FM1_ADC_CHANNEL 6u
#define FLOWMETER_FM2_ADC_CHANNEL 7u
#define FLOWMETER_FM3_ADC_CHANNEL 8u
#define FLOWMETER_FM4_ADC_CHANNEL 9u
/******************************************************************************
* Extern Function Declarations
******************************************************************************/
@ -42,13 +39,11 @@ typedef struct
* @brief Init function of the Flowmeter module.
*
* @param flowmeter_pst : Pointer to main strucutre of the module.
* adcHandle_pst : ADC handler f the flowmeter.
* channel_u32 : ADC channel of the connected sensor to use.
*
* @return Flow rate value.
*
*/
void FlowmeterInit(FlowmeterMain_st *flowmeter_pst, ADC_HandleTypeDef *adcHandle_pst, uint32 channel_u32);
void FlowmeterInit(FlowmeterMain_st *flowmeter_pst);
/**
* @brief Function to get flow value

View File

@ -13,8 +13,9 @@
* Include Header Files
******************************************************************************/
#include "grundfos.h"
#include "gpio.h"
#include "i2c.h"
#include "analogMeasurement.h"
#include "hal_gpio.h"
#include "hal_i2c.h"
/******************************************************************************
* Type declarations
******************************************************************************/
@ -22,40 +23,31 @@
/******************************************************************************
* Macro Constant Declarations
******************************************************************************/
#define GRUNDFOS_PMP_ADC_CHANNEL 5u
#define GRUNDFOS_PMP_ADC_REF_VOLTAGE 3.3f
#define GRUNDFOS_PMP_ADC_RESOLUTION 4095.0f /* 12-bit ADC */
#define GRUNDFOS_PMP_ADC_MODULE &hadc1
#define GRUNDFOS_PMP_ENABLE_GPIO_PORT GPIOB
#define GRUNDFOS_PMP_ENABLE_GPIO_PIN GPIO_PIN_15
#define GRUNDFOS_PMP_I2C_HANDLE &hi2c4
#define GRUNDFOS_PMP_INTERNAL_DAC_ADDR 0x61
#define GRUNDFOS_PMP_INTERNAL_DAC_ADDR (0x61 << 1)
/******************************************************************************
* Private function Declarations
******************************************************************************/
static uint32 GrundfosPmpReadVoltage(void);
static uint32 GrundfosPmpReadVoltage(uint8 channel_u8);
/******************************************************************************
* Extern Function Definitions
******************************************************************************/
void GrundfosPmpEnable(uint8 state_u8)
{
if(state_u8 == 1u)
if(state_u8 == 0u)
{
HAL_GPIO_WritePin(GRUNDFOS_PMP_ENABLE_GPIO_PORT, GRUNDFOS_PMP_ENABLE_GPIO_PIN, GPIO_PIN_SET);
HalGpioWrite(MAP_HAL_PMP_ENABLE, HAL_GPIO_STATE_HIGH); /* Pulling the line high stops the pump */
}
else
{
HAL_GPIO_WritePin(GRUNDFOS_PMP_ENABLE_GPIO_PORT, GRUNDFOS_PMP_ENABLE_GPIO_PIN, GPIO_PIN_RESET);
HalGpioWrite(MAP_HAL_PMP_ENABLE, HAL_GPIO_STATE_LOW);
}
}
uint32 GrundfosPmpFeedbackSpeed(void)
uint32 GrundfosPmpFeedbackSpeed(uint8 channel_u8)
{
uint32 feedbackSpeed_u32 = (GrundfosPmpReadVoltage()) * 360uL;
uint32 feedbackSpeed_u32 = (GrundfosPmpReadVoltage(channel_u8)) * 360uL;
return feedbackSpeed_u32;
}
@ -64,29 +56,31 @@ uint32 GrundfosPmpFeedbackSpeed(void)
bool GrundfosPmpSetSpeed(float32 setSpeed_f32)
{
uint8 data_au8[2];
uint16 dacVal_u16;
static volatile uint16 dacVal_u16 = 0u;
/* Limit the input range to 0V - 10V */
if (setSpeed_f32 < 0.0f)
{
setSpeed_f32 = 0.0f;
setSpeed_f32 = 0.0f;
}
else if (setSpeed_f32 > 10.0f)
{
setSpeed_f32 = 10.0f;
}
else
{
/* Do nothing. */
setSpeed_f32 = 10.0f;
}
dacVal_u16 = (uint16)(setSpeed_f32 * (GRUNDFOS_PMP_ADC_RESOLUTION / 10.0f));
/* Convert pump speed (0-10V) to DAC value (0-5V output) */
dacVal_u16 = (uint16)((setSpeed_f32 * 4095.0f) / 10.0f);
data_au8[0] = (uint8)(dacVal_u16 >> 4); /* Upper 8 bits */
data_au8[1] = (uint8)((dacVal_u16 & 0x0F) << 4); /* Lower 4 bits shifted to the upper nibble */
/* Format the 12-bit DAC value into the correct byte format */
data_au8[0] = (uint8)(dacVal_u16 >> 8); /* Upper 8 bits */
data_au8[1] = (uint8)(dacVal_u16 & 0xFF); /* Lower 8 bits */
return HAL_I2C_Master_Transmit(GRUNDFOS_PMP_I2C_HANDLE, GRUNDFOS_PMP_INTERNAL_DAC_ADDR, data_au8, 2u, HAL_MAX_DELAY) == HAL_OK;
return HalI2CMasterTransmit(MAP_HAL_GRUNDFOS_PMP_I2C_HANDLE,
GRUNDFOS_PMP_INTERNAL_DAC_ADDR,
data_au8, 2u) == NMS_ERR_NONE;
}
/******************************************************************************
* Private function Definitions
******************************************************************************/
@ -96,33 +90,13 @@ bool GrundfosPmpSetSpeed(float32 setSpeed_f32)
* @return ADC output voltage based on sensor reading.
*
*/
static uint32 GrundfosPmpReadVoltage(void)
static uint32 GrundfosPmpReadVoltage(uint8 channel_u8)
{
uint32_t adcVal_u32 = 0uL;
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = GRUNDFOS_PMP_ADC_CHANNEL; /* Set the channel specific to this flowmeter */
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
/* Convert ADC value to voltage (assuming 12-bit resolution and 3.3V reference) */
uint32 adcVal_u32 = 0uL;
AnalogMeasurementReadData(channel_u8, &adcVal_u32);
float32 voltage_f32 = (float32)adcVal_u32 * (ANALOG_MEAS_ADC_REF_VOLTAGE / ANALOG_MEAS_ADC_RESOLUTION);
if (HAL_ADC_ConfigChannel(GRUNDFOS_PMP_ADC_MODULE, &sConfig) != HAL_OK)
{
return 0.0f; /* ERROR */
}
if (HAL_ADC_Start(GRUNDFOS_PMP_ADC_MODULE) == HAL_OK)
{
if (HAL_ADC_PollForConversion(GRUNDFOS_PMP_ADC_MODULE, HAL_MAX_DELAY) == HAL_OK)
{
adcVal_u32 = HAL_ADC_GetValue(GRUNDFOS_PMP_ADC_MODULE);
}
HAL_ADC_Stop(GRUNDFOS_PMP_ADC_MODULE);
}
else
{
/* ERROR */
}
uint32 voltage_u32 = adcVal_u32 * (GRUNDFOS_PMP_ADC_REF_VOLTAGE / GRUNDFOS_PMP_ADC_RESOLUTION);
return voltage_u32;
return voltage_f32;
}

View File

@ -21,6 +21,11 @@
/******************************************************************************
* Type declarations
******************************************************************************/
typedef struct
{
uint32 channel_u32;
float32 rawQ_f32;
} GrundfosMain_st; /* Grundfos structure definition */
/******************************************************************************
* Macro Constant Declarations
@ -29,7 +34,7 @@
/******************************************************************************
* Extern Function Declarations
******************************************************************************/
extern uint32_t GrundfosPmpFeedbackSpeed(void);
extern void GrundfosPmpEnable(uint8_t state_u8);
extern bool GrundfosPmpSetSpeed(float setSpeed_f);
uint32 GrundfosPmpFeedbackSpeed(uint8 channel_u8);
void GrundfosPmpEnable(uint8_t state_u8);
bool GrundfosPmpSetSpeed(float setSpeed_f);
#endif /* GRUNDFOS_H_ */

View File

@ -13,44 +13,49 @@
#define OD_ENTRIES_H_
/* Device Indexes */
#define OD_ENTRY_PU_MOTOR_CTRL_INDEX 0x6000
#define OD_ENTRY_PU_COND_DATA_IN_INDEX 0x6001
#define OD_ENTRY_PU_COND_DATA_OUT_INDEX 0x6002
#define OD_ENTRY_PU_MOTOR_DATA_OUT_INDEX 0x6003
#define OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX 0x6004
#define OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX 0x6005
#define OD_ENTRY_PU_MOTOR_CTRL_INDEX 0x6000
#define OD_ENTRY_PU_COND_DATA_IN_INDEX 0x6001
#define OD_ENTRY_PU_COND_DATA_OUT_INDEX 0x6002
#define OD_ENTRY_PU_MOTOR_DATA_OUT_INDEX 0x6003
#define OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX 0x6004
#define OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX 0x6005
#define OD_ENTRY_PU_GRUNDFOS_PUMP_CONTROL_INDEX 0x6006
/* Device Sub-indexes */
#define OD_ENTRY_PU_MOTOR_CTRL_ID_SUB_INDEX 0x01
#define OD_ENTRY_PU_MOTOR_CTRL_CMD_SUB_INDEX 0x02
#define OD_ENTRY_PU_MOTOR_CTRL_POS_SUB_INDEX 0x03
#define OD_ENTRY_PU_MOTOR_CTRL_PRESSURE_SUB_INDEX 0x04
#define OD_ENTRY_PU_MOTOR_CTRL_FLOW_SUB_INDEX 0x05
#define OD_ENTRY_PU_MOTOR_CTRL_ID_SUB_INDEX 0x01
#define OD_ENTRY_PU_MOTOR_CTRL_CMD_SUB_INDEX 0x02
#define OD_ENTRY_PU_MOTOR_CTRL_POS_SUB_INDEX 0x03
#define OD_ENTRY_PU_MOTOR_CTRL_PRESSURE_SUB_INDEX 0x04
#define OD_ENTRY_PU_MOTOR_CTRL_FLOW_SUB_INDEX 0x05
#define OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX 0x01
#define OD_ENTRY_PU_COND2_DATA_IN_SUB_INDEX 0x03
#define OD_ENTRY_PU_COND3_DATA_IN_SUB_INDEX 0x05
#define OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX 0x01
#define OD_ENTRY_PU_COND2_DATA_IN_SUB_INDEX 0x03
#define OD_ENTRY_PU_COND3_DATA_IN_SUB_INDEX 0x05
#define OD_ENTRY_PU_TEMP1_DATA_IN_SUB_INDEX 0x02
#define OD_ENTRY_PU_TEMP2_DATA_IN_SUB_INDEX 0x04
#define OD_ENTRY_PU_TEMP3_DATA_IN_SUB_INDEX 0x06
#define OD_ENTRY_PU_TEMP1_DATA_IN_SUB_INDEX 0x02
#define OD_ENTRY_PU_TEMP2_DATA_IN_SUB_INDEX 0x04
#define OD_ENTRY_PU_TEMP3_DATA_IN_SUB_INDEX 0x06
#define OD_ENTRY_PU_COND1_DATA_OUT_SUB_INDEX 0x01
#define OD_ENTRY_PU_COND2_DATA_OUT_SUB_INDEX 0x03
#define OD_ENTRY_PU_COND3_DATA_OUT_SUB_INDEX 0x05
#define OD_ENTRY_PU_COND1_DATA_OUT_SUB_INDEX 0x01
#define OD_ENTRY_PU_COND2_DATA_OUT_SUB_INDEX 0x03
#define OD_ENTRY_PU_COND3_DATA_OUT_SUB_INDEX 0x05
#define OD_ENTRY_PU_TEMP1_DATA_OUT_SUB_INDEX 0x02
#define OD_ENTRY_PU_TEMP2_DATA_OUT_SUB_INDEX 0x04
#define OD_ENTRY_PU_TEMP3_DATA_OUT_SUB_INDEX 0x06
#define OD_ENTRY_PU_TEMP1_DATA_OUT_SUB_INDEX 0x02
#define OD_ENTRY_PU_TEMP2_DATA_OUT_SUB_INDEX 0x04
#define OD_ENTRY_PU_TEMP3_DATA_OUT_SUB_INDEX 0x06
#define OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX 0x01
#define OD_ENTRY_PU_FLOWMETER2_DATA_OUT_SUB_INDEX 0x02
#define OD_ENTRY_PU_FLOWMETER3_DATA_OUT_SUB_INDEX 0x03
#define OD_ENTRY_PU_FLOWMETER4_DATA_OUT_SUB_INDEX 0x04
#define OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX 0x01
#define OD_ENTRY_PU_FLOWMETER2_DATA_OUT_SUB_INDEX 0x02
#define OD_ENTRY_PU_FLOWMETER3_DATA_OUT_SUB_INDEX 0x03
#define OD_ENTRY_PU_FLOWMETER4_DATA_OUT_SUB_INDEX 0x04
#define OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX 0x01
#define OD_ENTRY_PU_PRESSURE2_DATA_OUT_SUB_INDEX 0x02
#define OD_ENTRY_PU_PRESSURE3_DATA_OUT_SUB_INDEX 0x03
#define OD_ENTRY_PU_PRESSURE4_DATA_OUT_SUB_INDEX 0x04
#define OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX 0x01
#define OD_ENTRY_PU_PRESSURE2_DATA_OUT_SUB_INDEX 0x02
#define OD_ENTRY_PU_PRESSURE3_DATA_OUT_SUB_INDEX 0x03
#define OD_ENTRY_PU_PRESSURE4_DATA_OUT_SUB_INDEX 0x04
#define OD_ENTRY_PU_GRUNDFOS_PUMP_ENABLE_SUB_INDEX 0x01
#define OD_ENTRY_PU_GRUNDFOS_PUMP_SET_SPEED_SUB_INDEX 0x02
#define OD_ENTRY_PU_GRUNDFOS_PUMP_FEEDBACK_SUB_INDEX 0x03
#endif /* OD_ENTRIES_H_ */

View File

@ -13,6 +13,7 @@
* Include Header Files
******************************************************************************/
#include "pressureSensor.h"
#include "analogMeasurement.h"
/******************************************************************************
* Type declarations
@ -21,27 +22,21 @@
/******************************************************************************
* Macro Constant Declarations
******************************************************************************/
#define PRESSURE_SENSOR_ADC_REF_VOLTAGE 3.3f
#define PRESSURE_SENSOR_ADC_RESOLUTION 4095.0f /* 12-bit ADC */
/******************************************************************************
* Private function Declarations
******************************************************************************/
static float PressureSensorReadVoltage(PressureSensorMain_st *pressureSensor_pst);
static float PressureSensorReadVoltage(uint32 channel_u32);
/******************************************************************************
* Extern Function Definitions
******************************************************************************/
void PressureSensorInit(PressureSensorMain_st *pressureSensor_pst,
ADC_HandleTypeDef *adcHandle_pst, uint32_t channel_u32)
void PressureSensorInit(PressureSensorMain_st *pressureSensor_pst)
{
if (pressureSensor_pst == NULL || adcHandle_pst == NULL)
if (pressureSensor_pst == NULL)
{
/* ERROR */
}
pressureSensor_pst->adcHandle_pst = adcHandle_pst;
pressureSensor_pst->channel_u32 = channel_u32;
}
@ -52,7 +47,7 @@ void PressureSensorGetVal(PressureSensorMain_st *pressureSensor_pst)
/* ERROR */
}
pressureSensor_pst->rawT_f32 = (PressureSensorReadVoltage(pressureSensor_pst) - 0.5f) / 0.2f;
pressureSensor_pst->rawT_f32 = (PressureSensorReadVoltage(pressureSensor_pst->channel_u32) - 0.5f) / 0.2f;
}
@ -67,40 +62,12 @@ void PressureSensorGetVal(PressureSensorMain_st *pressureSensor_pst)
* @return ADC output voltage based on sensor reading.
*
*/
static float32 PressureSensorReadVoltage(PressureSensorMain_st *pressureSensor_pst)
static float32 PressureSensorReadVoltage(uint32 channel_u32)
{
uint32 adcVal_u32 = 0uL;
if (pressureSensor_pst == NULL || pressureSensor_pst->adcHandle_pst == NULL)
{
return 0.0f; /* Error Case */
}
ADC_ChannelConfTypeDef sConfig = {0};
sConfig.Channel = pressureSensor_pst->channel_u32; /* Set the channel specific to this flowmeter */
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_12CYCLES_5;
if (HAL_ADC_ConfigChannel(pressureSensor_pst->adcHandle_pst, &sConfig) != HAL_OK)
{
return 0.0f; /* ERROR */
}
/* Start ADC conversion and poll for completion */
if (HAL_ADC_Start(pressureSensor_pst->adcHandle_pst) == HAL_OK)
{
if (HAL_ADC_PollForConversion(pressureSensor_pst->adcHandle_pst, HAL_MAX_DELAY) == HAL_OK)
{
adcVal_u32 = HAL_ADC_GetValue(pressureSensor_pst->adcHandle_pst);
}
HAL_ADC_Stop(pressureSensor_pst->adcHandle_pst);
}
else
{
/* ERROR */
}
/* Convert ADC value to voltage (assuming 12-bit resolution and 3.3V reference) */
float32 voltage_f32 = (float32)adcVal_u32 * (PRESSURE_SENSOR_ADC_REF_VOLTAGE / PRESSURE_SENSOR_ADC_RESOLUTION);
uint32 adcVal_u32 = 0uL;
AnalogMeasurementReadData(channel_u32, &adcVal_u32);
float32 voltage_f32 = (float32)adcVal_u32 * (ANALOG_MEAS_ADC_REF_VOLTAGE / ANALOG_MEAS_ADC_RESOLUTION);
return voltage_f32;
}

View File

@ -19,7 +19,6 @@
******************************************************************************/
typedef struct
{
ADC_HandleTypeDef *adcHandle_pst;
uint32 channel_u32;
float32 rawT_f32;
} PressureSensorMain_st; /* HubaPressure sensor structure definition */
@ -27,10 +26,7 @@ typedef struct
/******************************************************************************
* Macro Constant Declarations
******************************************************************************/
#define PRESSURE_SENSOR_PS1_ADC_CHANNEL 1u
#define PRESSURE_SENSOR_PS2_ADC_CHANNEL 2u
#define PRESSURE_SENSOR_PS3_ADC_CHANNEL 3u
#define PRESSURE_SENSOR_PS4_ADC_CHANNEL 4u
/******************************************************************************
* Extern Function Declarations
******************************************************************************/
@ -38,14 +34,11 @@ typedef struct
* @brief Init function of the Pressure sensor module.
*
* @param pressureSensor_pst : Pointer to main strucutre of the module.
* adcHandle_pst : ADC handler f the flowmeter.
* channel_u32 : ADC channel of the connected sensor to use.
*
* @return Pressure value.
*
*/
void PressureSensorInit(PressureSensorMain_st *pressureSensor_pst,
ADC_HandleTypeDef *adcHandle_pst, uint32 channel_u32);
void PressureSensorInit(PressureSensorMain_st *pressureSensor_pst);
/**
* @brief Function to get pressure value.

View File

@ -15,8 +15,10 @@
#include "processBoard.h"
#include "flowmeter.h"
#include "pressureSensor.h"
#include "grundfos.h"
#include "od_entries.h"
#include "co_odaccess.h"
#include "nms_can.h"
#include "analogMeasurement.h"
/******************************************************************************
* Type declarations
******************************************************************************/
@ -24,14 +26,14 @@
/******************************************************************************
* Macro Constant Declarations
******************************************************************************/
#define PROCESS_BOARD_VALVE_POS_INDEX 0x6002
#define PROCESS_BOARD_VALVE_FLOW_INDEX 0x6006
#define PROCESS_BOARD_VALVE_PRESSURE_INDEX 0x6001
#define PROCESS_BOARD_VALVE_POS_INDEX 0x6002
#define PROCESS_BOARD_VALVE_FLOW_INDEX 0x6006
#define PROCESS_BOARD_VALVE_PRESSURE_INDEX 0x6001
#define PROCESS_BOARD_VALVE_SUB_INDEX 0x0
#define PROCESS_BOARD_VALVE_SUB_INDEX 0x0
#define PROCESS_BOARD_FLOWMETER_ADC_MODULE &hadc1
#define PROCESS_BOARD_PRESSURE_SENSOR_ADC_MODULE &hadc1
#define PU_CANOPEN_SLAVE_LINE 0u
#define PU_CANOPEN_MASTER_LINE 1u
/******************************************************************************
* Global variables
******************************************************************************/
@ -49,6 +51,8 @@ PressureSensorMain_st pressureSensorPS2_gst;
PressureSensorMain_st pressureSensorPS3_gst;
PressureSensorMain_st pressureSensorPS4_gst;
GrundfosMain_st grundfosPMP_gst;
ProcessBoardCondDataSt condBoard1_gst;
ProcessBoardCondDataSt condBoard2_gst;
ProcessBoardCondDataSt condBoard3_gst;
@ -70,9 +74,10 @@ static void ProcessBoardTriggerMvCartCtrl(uint8 motorId_u8, uint8 flowRate_u8, u
static void ProcessBoardReadCondDataIN(void);
static void ProcessBoardWriteCondDataOUT(void);
static void ProcessBoardReadMvDataIN(void);
static void ProcessBoardFlowmeterDataOUT(FlowmeterMain_st flowmeter_st);
static void ProcessBoardPressureSensorDataOUT(PressureSensorMain_st pressureSensor_st);
static void ProcessBoardFlowmeterDataOUT(float32 rawQ_f32);
static void ProcessBoardPressureSensorDataOUT(float32 rawT_f32);
static void ProcessBoardPumpSpeedDataOUT(uint32 pmpSpeed_u32);
static void ProcessBoardGrundfosPumpHandler(void);
/******************************************************************************
* Extern Function Declarations
******************************************************************************/
@ -80,48 +85,73 @@ void ProcessBoardInit(void)
{
motorCmd_gu8 = 0u;
FlowmeterInit(&flowmeterFM1_gst, PROCESS_BOARD_FLOWMETER_ADC_MODULE, FLOWMETER_FM1_ADC_CHANNEL);
PressureSensorInit(&pressureSensorPS1_gst, PROCESS_BOARD_PRESSURE_SENSOR_ADC_MODULE, PRESSURE_SENSOR_PS1_ADC_CHANNEL);
/* Initializing the structures (Pressure sensor, Flow
* meter, and Grundfos) with their respective ADC channel */
pressureSensorPS1_gst.channel_u32 = PS1_ADC_CHANNEL;
pressureSensorPS2_gst.channel_u32 = PS2_ADC_CHANNEL;
pressureSensorPS3_gst.channel_u32 = PS3_ADC_CHANNEL;
pressureSensorPS4_gst.channel_u32 = PS4_ADC_CHANNEL;
FlowmeterInit(&flowmeterFM2_gst, PROCESS_BOARD_FLOWMETER_ADC_MODULE, FLOWMETER_FM2_ADC_CHANNEL);
PressureSensorInit(&pressureSensorPS2_gst, PROCESS_BOARD_PRESSURE_SENSOR_ADC_MODULE, PRESSURE_SENSOR_PS2_ADC_CHANNEL);
grundfosPMP_gst.channel_u32 = PMP_ADC_CHANNEL;
FlowmeterInit(&flowmeterFM3_gst, PROCESS_BOARD_FLOWMETER_ADC_MODULE, FLOWMETER_FM3_ADC_CHANNEL);
PressureSensorInit(&pressureSensorPS3_gst, PROCESS_BOARD_PRESSURE_SENSOR_ADC_MODULE, PRESSURE_SENSOR_PS3_ADC_CHANNEL);
FlowmeterInit(&flowmeterFM4_gst, PROCESS_BOARD_FLOWMETER_ADC_MODULE, FLOWMETER_FM4_ADC_CHANNEL);
PressureSensorInit(&pressureSensorPS4_gst, PROCESS_BOARD_PRESSURE_SENSOR_ADC_MODULE, PRESSURE_SENSOR_PS4_ADC_CHANNEL);
flowmeterFM1_gst.channel_u32 = FM1_ADC_CHANNEL;
flowmeterFM2_gst.channel_u32 = FM2_ADC_CHANNEL;
flowmeterFM3_gst.channel_u32 = FM3_ADC_CHANNEL;
flowmeterFM4_gst.channel_u32 = FM4_ADC_CHANNEL;
FlowmeterInit(&flowmeterFM1_gst);
FlowmeterInit(&flowmeterFM2_gst);
FlowmeterInit(&flowmeterFM3_gst);
FlowmeterInit(&flowmeterFM4_gst);
}
void ProcessBoardRun(void)
{
uint8 id_u8;
uint8 motorCmd_u8;
uint8 posData_u8;
uint8 flowRate_u8;
uint8 pressure_u8;
coOdGetObj_u8(OD_ENTRY_PU_MOTOR_CTRL_INDEX, OD_ENTRY_PU_MOTOR_CTRL_ID_SUB_INDEX, &id_u8);
coOdGetObj_u8(OD_ENTRY_PU_MOTOR_CTRL_INDEX, OD_ENTRY_PU_MOTOR_CTRL_CMD_SUB_INDEX, &motorCmd_u8);
coOdGetObj_u8(OD_ENTRY_PU_MOTOR_CTRL_INDEX, OD_ENTRY_PU_MOTOR_CTRL_POS_SUB_INDEX, &posData_u8);
coOdGetObj_u8(OD_ENTRY_PU_MOTOR_CTRL_INDEX, OD_ENTRY_PU_MOTOR_CTRL_PRESSURE_SUB_INDEX, &flowRate_u8);
coOdGetObj_u8(OD_ENTRY_PU_MOTOR_CTRL_INDEX, OD_ENTRY_PU_MOTOR_CTRL_FLOW_SUB_INDEX, &pressure_u8);
uint8 id_u8 = 0u;
uint8 motorCmd_u8 = 0u;
uint8 posData_u8 = 0u;
uint8 flowRate_u8 = 0u;
uint8 pressure_u8 = 0u;
AnalogMesaurementRun();
/* DEBUG code to be replaced. Logic to be changed based on state machine
* implementation. */
if(motorCmd_u8 == 1u)
{
ProcessBoardTriggerMvPosCtrl(11, posData_u8);
ProcessBoardTriggerMvPosCtrl(11, posData_u8); /* DEBUG */
}
else
{
ProcessBoardTriggerMvCartCtrl(id_u8, flowRate_u8, pressure_u8);
}
/* Flowmeter data IN */
FlowmeterGetFlow(&flowmeterFM1_gst);
FlowmeterGetFlow(&flowmeterFM2_gst);
FlowmeterGetFlow(&flowmeterFM3_gst);
FlowmeterGetFlow(&flowmeterFM4_gst);
/* Pressure sensor data IN */
PressureSensorGetVal(&pressureSensorPS1_gst);
ProcessBoardFlowmeterDataOUT(flowmeterFM4_gst);
ProcessBoardPressureSensorDataOUT(pressureSensorPS1_gst);
PressureSensorGetVal(&pressureSensorPS2_gst);
PressureSensorGetVal(&pressureSensorPS3_gst);
PressureSensorGetVal(&pressureSensorPS4_gst);
/* Flowmeter data OUT */
ProcessBoardFlowmeterDataOUT(flowmeterFM1_gst.rawQ_f32);
ProcessBoardFlowmeterDataOUT(flowmeterFM2_gst.rawQ_f32);
ProcessBoardFlowmeterDataOUT(flowmeterFM3_gst.rawQ_f32);
ProcessBoardFlowmeterDataOUT(flowmeterFM4_gst.rawQ_f32);
/* Pressure sensor data OUT */
ProcessBoardPressureSensorDataOUT(pressureSensorPS1_gst.rawT_f32);
ProcessBoardPressureSensorDataOUT(pressureSensorPS2_gst.rawT_f32);
ProcessBoardPressureSensorDataOUT(pressureSensorPS3_gst.rawT_f32);
ProcessBoardPressureSensorDataOUT(pressureSensorPS4_gst.rawT_f32);
ProcessBoardGrundfosPumpHandler();
ProcessBoardReadCondDataIN();
ProcessBoardWriteCondDataOUT();
}
@ -130,6 +160,88 @@ void ProcessBoardRun(void)
/******************************************************************************
* Private function definitions
******************************************************************************/
//static void ProcessBoardGrundfosPumpHandler(void)
//{
// uint32 pmpSpeed_u32 = 0uL;
// uint8 mode_u8 = 0u;
// uint8 speed_u8 = 0u;
//
// NmsCanGetObj_u8(OD_ENTRY_PU_GRUNDFOS_PUMP_CONTROL_INDEX, OD_ENTRY_PU_GRUNDFOS_PUMP_ENABLE_SUB_INDEX, &mode_u8);
// NmsCanGetObj_u8(OD_ENTRY_PU_GRUNDFOS_PUMP_CONTROL_INDEX, OD_ENTRY_PU_GRUNDFOS_PUMP_SET_SPEED_SUB_INDEX, &speed_u8);
//
// GrundfosPmpEnable(mode_u8);
// if(mode_u8 == 1u)
// {
// GrundfosPmpSetSpeed(speed_u8);
// /* Grundfos Pump feedback speed OUT */
// pmpSpeed_u32 = GrundfosPmpFeedbackSpeed(PMP_ADC_CHANNEL);
// }
// else
// {
// pmpSpeed_u32 = 0uL;
// }
// ProcessBoardPumpSpeedDataOUT(pmpSpeed_u32);
//}
static void ProcessBoardGrundfosPumpHandler(void)
{
uint32 pmpSpeed_u32 = 0uL;
uint8 mode_u8 = 0u;
static uint8 speed_u8 = 0u;
static uint32 elapsedTime_s = 0u;
static enum { INCREASING, DECREASING } speedState = INCREASING;
NmsCanGetObj_u8(OD_ENTRY_PU_GRUNDFOS_PUMP_CONTROL_INDEX, OD_ENTRY_PU_GRUNDFOS_PUMP_ENABLE_SUB_INDEX, &mode_u8);
// Only modify speed every 15 minutes (900 seconds)
if (elapsedTime_s >= 900)
{
elapsedTime_s = 0; // Reset time counter
if (speedState == INCREASING)
{
if (speed_u8 < 10)
{
speed_u8 += 2;
}
if (speed_u8 >= 10)
{
speedState = DECREASING; // Switch to decreasing mode
}
}
else // DECREASING
{
if (speed_u8 > 0)
{
speed_u8 -= 2;
}
if (speed_u8 == 0)
{
speedState = INCREASING; // Switch back to increasing mode
}
}
}
else
{
elapsedTime_s++; // Increment elapsed time
}
GrundfosPmpEnable(mode_u8);
if (mode_u8 == 1u)
{
GrundfosPmpSetSpeed(speed_u8);
/* Grundfos Pump feedback speed OUT */
pmpSpeed_u32 = GrundfosPmpFeedbackSpeed(PMP_ADC_CHANNEL);
}
else
{
pmpSpeed_u32 = 0uL;
}
ProcessBoardPumpSpeedDataOUT(pmpSpeed_u32);
}
static void ProcessBoardTriggerMvPosCtrl(uint8 motorId_u8, uint8 posData_u8)
{
@ -144,49 +256,55 @@ static void ProcessBoardTriggerMvCartCtrl(uint8 motorId_u8, uint8 flowRate_u8, u
static void ProcessBoardReadCondDataIN(void)
{
coOdGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, &condBoard1_gst.conductivityData_u32);
coOdGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_TEMP1_DATA_IN_SUB_INDEX, &condBoard1_gst.temperature_u32);
NmsCanGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, &condBoard1_gst.conductivityData_u32);
NmsCanGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_TEMP1_DATA_IN_SUB_INDEX, &condBoard1_gst.temperature_u32);
coOdGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, &condBoard2_gst.conductivityData_u32);
coOdGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_TEMP2_DATA_IN_SUB_INDEX, &condBoard2_gst.temperature_u32);
NmsCanGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, &condBoard2_gst.conductivityData_u32);
NmsCanGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_TEMP2_DATA_IN_SUB_INDEX, &condBoard2_gst.temperature_u32);
coOdGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, &condBoard3_gst.conductivityData_u32);
coOdGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_TEMP3_DATA_IN_SUB_INDEX, &condBoard3_gst.temperature_u32);
NmsCanGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, &condBoard3_gst.conductivityData_u32);
NmsCanGetObj_u32(OD_ENTRY_PU_COND_DATA_IN_INDEX, OD_ENTRY_PU_TEMP3_DATA_IN_SUB_INDEX, &condBoard3_gst.temperature_u32);
}
static void ProcessBoardWriteCondDataOUT(void)
{
coOdPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, condBoard1_gst.conductivityData_u32);
coOdPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_TEMP1_DATA_IN_SUB_INDEX, condBoard1_gst.temperature_u32);
NmsCanPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_COND1_DATA_IN_SUB_INDEX, condBoard1_gst.conductivityData_u32);
NmsCanPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_TEMP1_DATA_IN_SUB_INDEX, condBoard1_gst.temperature_u32);
coOdPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_COND2_DATA_IN_SUB_INDEX, condBoard2_gst.conductivityData_u32);
coOdPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_TEMP2_DATA_IN_SUB_INDEX, condBoard2_gst.temperature_u32);
NmsCanPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_COND2_DATA_IN_SUB_INDEX, condBoard2_gst.conductivityData_u32);
NmsCanPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_TEMP2_DATA_IN_SUB_INDEX, condBoard2_gst.temperature_u32);
coOdPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_COND3_DATA_IN_SUB_INDEX, condBoard3_gst.conductivityData_u32);
coOdPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_TEMP3_DATA_IN_SUB_INDEX, condBoard3_gst.temperature_u32);
NmsCanPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_COND3_DATA_IN_SUB_INDEX, condBoard3_gst.conductivityData_u32);
NmsCanPutObj_u32(OD_ENTRY_PU_COND_DATA_OUT_INDEX, OD_ENTRY_PU_TEMP3_DATA_IN_SUB_INDEX, condBoard3_gst.temperature_u32);
}
static void ProcessBoardFlowmeterDataOUT(FlowmeterMain_st flowmeter_st)
static void ProcessBoardFlowmeterDataOUT(float32 rawQ_f32)
{
coOdPutObj_r32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, flowmeterFM1_gst.rawQ_f32);
coOdPutObj_r32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, flowmeterFM2_gst.rawQ_f32);
coOdPutObj_r32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, flowmeterFM3_gst.rawQ_f32);
coOdPutObj_r32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, flowmeterFM4_gst.rawQ_f32);
NmsCanPutObj_f32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, rawQ_f32);
NmsCanPutObj_f32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, rawQ_f32);
NmsCanPutObj_f32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, rawQ_f32);
NmsCanPutObj_f32(OD_ENTRY_PU_FLOWMETER_DATA_OUT_INDEX, OD_ENTRY_PU_FLOWMETER1_DATA_OUT_SUB_INDEX, rawQ_f32);
}
static void ProcessBoardPressureSensorDataOUT(PressureSensorMain_st pressureSensor_st)
static void ProcessBoardPressureSensorDataOUT(float32 rawT_f32)
{
coOdPutObj_r32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, pressureSensorPS1_gst.rawT_f32);
coOdPutObj_r32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, pressureSensorPS2_gst.rawT_f32);
coOdPutObj_r32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, pressureSensorPS3_gst.rawT_f32);
coOdPutObj_r32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, pressureSensorPS4_gst.rawT_f32);
NmsCanPutObj_f32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, rawT_f32);
NmsCanPutObj_f32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, rawT_f32);
NmsCanPutObj_f32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, rawT_f32);
NmsCanPutObj_f32(OD_ENTRY_PU_PRESSURE_DATA_OUT_INDEX, OD_ENTRY_PU_PRESSURE1_DATA_OUT_SUB_INDEX, rawT_f32);
}
static void ProcessBoardPumpSpeedDataOUT(uint32 pmpSpeed_u32)
{
NmsCanPutObj_u32(OD_ENTRY_PU_GRUNDFOS_PUMP_CONTROL_INDEX, OD_ENTRY_PU_GRUNDFOS_PUMP_FEEDBACK_SUB_INDEX, pmpSpeed_u32);
}
static void ProcessBoardReadMvDataIN(void)
{
/* To be implemented */
// NmsCanGetObj_u8(uint8 canLine_u8, uint16 index_u16, uint8 subIndex_u8, uint8 *pObj_pu8);
}

View File

@ -0,0 +1,298 @@
/**
* @file batch_endurance_testbench.c
*
* @brief Batch mode test bench:
* 1. Write to all nodes (at 100ms intervals)
* 2. Read all nodes
* 3. Verify positions (retry mismatch up to 2 times)
* 4. Cycle complete reset for next iteration
*
* @copyright
*/
#include "enduranceTestBench.h"
#include "stdlib.h"
/* CANopen includes */
#include <gen_define.h>
#include <co_canopen.h>
#include "../nms_hal/hal_system.h"
/******************************************************************************
* Macro constant declarations
******************************************************************************/
#define ENDURANCE_TEST_BENCH_MAX_RETRY_CNT 3u
#define ENDURANCE_TEST_BENCH_TIMEOUT 1000u
#define ENDURANCE_TEST_BENCH_LSS_NODE_COUNT 20u
#define ENDURANCE_TEST_BENCH_POSITION_SETPOINT_INDEX 0x6002
#define ENDURANCE_TEST_BENCH_POSITION_SETPOINT_SUB_INDEX 0x0
#define ENDURANCE_TEST_BENCH_POSITION_FEEDBACK_INDEX 0x6004
#define ENDURANCE_TEST_BENCH_POSITION_FEEDBACK_SUB_INDEX 0x0
/* Batch delay between node operations (in ms) */
#define NODE_OP_DELAY_MS 100u
/******************************************************************************
* Type Declarations
******************************************************************************/
typedef enum
{
TEST_BENCH_BATCH_WRITE, /* Write to nodes in batch */
TEST_BENCH_BATCH_WRITE_WAIT, /* Wait between writes */
TEST_BENCH_BATCH_READ, /* Read all nodes */
TEST_BENCH_BATCH_READ_WAIT, /* Wait between reads */
TEST_BENCH_BATCH_VERIFY, /* Verify all nodes */
TEST_BENCH_CYCLE_COMPLETE, /* End of cycle, reset for next iteration */
TEST_BENCH_IDLE /* Idle state (optional) */
} SdlTestBenchState_en;
typedef enum
{
TEST_BENCH_DATA_VERIF_DEFAULT,
TEST_BENCH_DATA_VERIF_SUCCESS,
TEST_BENCH_DATA_VERIF_FAILURE,
TEST_BENCH_DATA_VERIF_SKIPPED,
} TestBenchStatus_en;
typedef struct
{
uint8 targetPositions_gau8[ENDURANCE_TEST_BENCH_LSS_NODE_COUNT];
uint8 readPosition_gau8[ENDURANCE_TEST_BENCH_LSS_NODE_COUNT];
TestBenchStatus_en status_en[ENDURANCE_TEST_BENCH_LSS_NODE_COUNT];
} TestBenchData_en;
/******************************************************************************
* Global variable declarations
******************************************************************************/
static TestBenchData_en testBenchData_en;
static uint8 currentNode_gu8 = 0u;
static SdlTestBenchState_en testBenchState_en = TEST_BENCH_IDLE;
static uint32 readPosition_gu32;
static uint8 storedTargetPos = 0u; /* Flag: target written to current node */
static uint8 readMismatchRetries_u8 = 0u; /* Retry count for verify mismatches */
static uint64 writeTime_u64 = 0uLL;
static uint64 readExecutedTime_u64 = 0uLL;
static uint64 cycleStartTime_u64 = 0uLL;
static uint8 retries_u8 = 0u; /* General retry counter for SDO communication */
/******************************************************************************
* Public Function Definitions
******************************************************************************/
void TestRun(void)
{
uint64 currentTime_u64;
HalSystemGetRunTimeMs(&currentTime_u64);
/* Initialization: start new cycle if in idle or cycle complete state */
if (testBenchState_en == TEST_BENCH_IDLE || testBenchState_en == TEST_BENCH_CYCLE_COMPLETE)
{
/* Prepare new cycle: reset all node statuses and choose new target positions */
for (uint8 i = 0u; i < ENDURANCE_TEST_BENCH_LSS_NODE_COUNT; i++)
{
testBenchData_en.targetPositions_gau8[i] = (uint8)(rand() % 256);
testBenchData_en.readPosition_gau8[i] = 0u;
testBenchData_en.status_en[i] = TEST_BENCH_DATA_VERIF_DEFAULT;
}
currentNode_gu8 = 0u;
storedTargetPos = 0u;
retries_u8 = 0u;
readMismatchRetries_u8 = 0u;
cycleStartTime_u64 = currentTime_u64;
testBenchState_en = TEST_BENCH_BATCH_WRITE;
}
switch (testBenchState_en)
{
/* -------------------- Batch Write -------------------- */
case TEST_BENCH_BATCH_WRITE:
{
if (currentNode_gu8 < ENDURANCE_TEST_BENCH_LSS_NODE_COUNT)
{
if (storedTargetPos == 0)
{
/* Use the pre-assigned target value for this node */
uint8 value_u8 = testBenchData_en.targetPositions_gau8[currentNode_gu8];
RET_T retVal_en = coSdoWrite(
(currentNode_gu8 + 1),
ENDURANCE_TEST_BENCH_POSITION_SETPOINT_INDEX,
ENDURANCE_TEST_BENCH_POSITION_SETPOINT_SUB_INDEX,
&value_u8,
sizeof(uint8),
CO_FALSE,
ENDURANCE_TEST_BENCH_TIMEOUT
);
if (retVal_en == RET_OK)
{
storedTargetPos = 1; /* Mark that target is written for this node */
HalSystemGetRunTimeMs(&writeTime_u64);
retries_u8 = 0u;
testBenchState_en = TEST_BENCH_BATCH_WRITE_WAIT;
}
else
{
retries_u8++;
if (retries_u8 >= ENDURANCE_TEST_BENCH_MAX_RETRY_CNT)
{
testBenchData_en.status_en[currentNode_gu8] = TEST_BENCH_DATA_VERIF_SKIPPED;
/* Mark node as skipped and move on */
currentNode_gu8++;
retries_u8 = 0u;
storedTargetPos = 0u;
testBenchState_en = TEST_BENCH_BATCH_WRITE;
}
}
}
}
else
{
/* Finished writing to all nodes */
currentNode_gu8 = 0u; /* Reset index for read phase */
testBenchState_en = TEST_BENCH_BATCH_READ;
}
break;
}
case TEST_BENCH_BATCH_WRITE_WAIT:
{
/* Wait 100ms between writes */
if ((currentTime_u64 - writeTime_u64) >= 500)
{
/* Move to next node write */
currentNode_gu8++;
storedTargetPos = 0u; /* Reset for next node */
testBenchState_en = TEST_BENCH_BATCH_WRITE;
}
break;
}
/* -------------------- Batch Read -------------------- */
case TEST_BENCH_BATCH_READ:
{
if (currentNode_gu8 < ENDURANCE_TEST_BENCH_LSS_NODE_COUNT)
{
RET_T retVal_en = coSdoRead(
(currentNode_gu8 + 1),
ENDURANCE_TEST_BENCH_POSITION_FEEDBACK_INDEX,
ENDURANCE_TEST_BENCH_POSITION_FEEDBACK_SUB_INDEX,
(uint8*)&readPosition_gu32,
sizeof(uint32),
CO_FALSE,
ENDURANCE_TEST_BENCH_TIMEOUT
);
if (retVal_en == RET_OK)
{
retries_u8 = 0u;
/* The read indication callback is assumed to update
* testBenchData_en.readPosition_gau8[currentNode_gu8] and
* then we simply continue to next node after a small delay.
*/
HalSystemGetRunTimeMs(&readExecutedTime_u64);
testBenchData_en.readPosition_gau8[currentNode_gu8] = (uint8)readPosition_gu32;
testBenchState_en = TEST_BENCH_BATCH_READ_WAIT;
}
else if (retVal_en == RET_SERVICE_BUSY && retries_u8 < ENDURANCE_TEST_BENCH_MAX_RETRY_CNT)
{
retries_u8++;
}
else
{
/* If read fails, mark as skipped and move on */
testBenchData_en.status_en[currentNode_gu8] = TEST_BENCH_DATA_VERIF_SKIPPED;
currentNode_gu8++;
retries_u8 = 0u;
}
}
else
{
/* Finished reading all nodes */
currentNode_gu8 = 0u; /* Reset for verification phase */
testBenchState_en = TEST_BENCH_BATCH_VERIFY;
}
break;
}
case TEST_BENCH_BATCH_READ_WAIT:
{
/* Wait 100ms between node reads */
if ((currentTime_u64 - readExecutedTime_u64) >= 10)
{
currentNode_gu8++;
testBenchState_en = TEST_BENCH_BATCH_READ;
}
break;
}
/* -------------------- Batch Verify -------------------- */
case TEST_BENCH_BATCH_VERIFY:
{
if (currentNode_gu8 < ENDURANCE_TEST_BENCH_LSS_NODE_COUNT)
{
/* Process only if the node was not already skipped */
if (testBenchData_en.status_en[currentNode_gu8] != TEST_BENCH_DATA_VERIF_SKIPPED)
{
uint8 diff = abs(testBenchData_en.targetPositions_gau8[currentNode_gu8] -
testBenchData_en.readPosition_gau8[currentNode_gu8]);
if (diff <= 1)
{
testBenchData_en.status_en[currentNode_gu8] = TEST_BENCH_DATA_VERIF_SUCCESS;
}
else
{
testBenchData_en.status_en[currentNode_gu8] = TEST_BENCH_DATA_VERIF_FAILURE;
}
}
/* Move to the next node in any case */
currentNode_gu8++;
testBenchState_en = TEST_BENCH_BATCH_VERIFY;
}
else
{
/* All nodes verified; complete cycle */
testBenchState_en = TEST_BENCH_CYCLE_COMPLETE;
}
break;
}
/* -------------------- Cycle Complete -------------------- */
case TEST_BENCH_CYCLE_COMPLETE:
{
/* Optionally, you can log or process the batch results here */
/* Reset all node data for the next cycle */
for (uint8 i = 0u; i < ENDURANCE_TEST_BENCH_LSS_NODE_COUNT; i++)
{
testBenchData_en.targetPositions_gau8[i] = 0u;
testBenchData_en.readPosition_gau8[i] = 0u;
testBenchData_en.status_en[i] = TEST_BENCH_DATA_VERIF_DEFAULT;
}
currentNode_gu8 = 0u;
storedTargetPos = 0u;
retries_u8 = 0u;
readMismatchRetries_u8 = 0u;
/* Start next cycle */
testBenchState_en = TEST_BENCH_IDLE;
break;
}
default:
break;
}
}
/******************************************************************************
* Callback Functions
******************************************************************************/
void TestReadInd(uint8 sdoNr_u8, uint16 index_u16, uint8 subIndex_u8, uint32 errorVal_u32)
{
HalSystemGetRunTimeMs(&writeTime_u64);
}
void TestWriteInd(uint8 sdoNr_u8, uint16 index_u16, uint8 subIndex_u8, uint32 size, uint32 errorVal_u32)
{
HalSystemGetRunTimeMs(&readExecutedTime_u64);
//testBenchData_en.readPosition_gau8[currentNode_gu8] = (uint8)readPosition_gu32;
}

View File

@ -0,0 +1,32 @@
/**
* @file test.h
*
* @copyright Nehemis SARL reserves all rights even in the event of industrial
* property rights. We reserve all rights of disposal such as
* copying and passing on to third parties.
*
* @brief
*
*/
#ifndef TEST_H_
#define TEST_H_
/******************************************************************************
* Include Header Files
******************************************************************************/
/******************************************************************************
* Type declarations
******************************************************************************/
/******************************************************************************
* Extern Function Declarations
******************************************************************************/
void TestRun(void);
void TestInit(void);
void TestWriteInd(uint8 sdoNr, UNSIGNED16 index, uint8 subIndex, UNSIGNED32 errorVal);
void TestReadInd(uint8 sdoNr, UNSIGNED16 index, uint8 subIndex, UNSIGNED32 size, UNSIGNED32 errorVal);
#endif /* TEST_H_ */

View File

@ -1,249 +0,0 @@
/**
* @file hal_system.c
* @copyright Nehemis SARL reserves all rights even in the event of industrial
* property rights. We reserve all rights of disposal such as
* copying and passing on to third parties.
*
*
* @brief HAL layer for the SYSTEM module.
* - The system reset cause such as :
* 1. Software reset
* 2. Watchdog reset
* 3. Power on reset
* 4. Optional byte load reset
* 5. Low power reset
* 6. Pin reset
* - The NVIC enable/disable interrupts.
* - The serial number of the MCU.
*/
/******************************************************************************
* Include Header Files
******************************************************************************/
#include "hal_system.h"
/* cubeMX */
#include "main.h"
/******************************************************************************
* Macro Constant Declarations
******************************************************************************/
#define HAL_SYSTEM_STACK_GUARD 0xCDu
/******************************************************************************
* Module Global Variable Declarations
******************************************************************************/
static uint64 systemStepCounter_gu64;
static uint64 systemPeriodMsToUs_gu64;
static uint64 systemTickLoadValue_gu64;
static uint32 resetStatusRegister_gu32;
/******************************************************************************
* Static Function Declarations
******************************************************************************/
/******************************************************************************
* Extern Function Definitions
******************************************************************************/
uint32 HalSystemInit(void)
{
uint32 error_u32 = NMS_ERR_NONE;
resetStatusRegister_gu32 = RCC->CSR;
RCC->CSR |= RCC_CSR_RMVF; /* RMVF = ReMoVe Flag. Reset the reset cause register for the next reboot. */
systemPeriodMsToUs_gu64 = HAL_GetTickFreq() * 1000uLL;
systemTickLoadValue_gu64 = (uint64)(SysTick->LOAD);
systemStepCounter_gu64 = 0uLL;
return error_u32;
}
uint32 HalSystemGetRunTimeUs(uint64 * resultUs_pu64)
{
static uint64 previousTimeUs_u64 = 0uLL;
uint32 error_u32 = NMS_ERR_NONE;
uint64 timeUs_u64 = 0uLL;
/* Make a copy in case of multiple function instance at the same time */
uint64 copySystemStepCounter_u64 = systemStepCounter_gu64;
/* First make a copy of the systemStepCounter to be able to check rollback further on.
* Also copy current value of the System Tick Timer to avoid any dynamic update during calculation.
* Then translate in microsecond & sum both timing information (step counter + tick value) to get the most
* accurate resolution of the system runtime.
*/
uint64 copyPreviousTimeUs_u64 = previousTimeUs_u64;
uint64 tickValue_u64 = (uint64)(SysTick->VAL);
timeUs_u64 = copySystemStepCounter_u64 * systemPeriodMsToUs_gu64;
timeUs_u64 += ((systemTickLoadValue_gu64 - tickValue_u64) * systemPeriodMsToUs_gu64) / systemTickLoadValue_gu64;
/* We check here if the interruption of the systick happened during our operations and correct it accordingly */
if(timeUs_u64 <= (uint64)(systemStepCounter_gu64 * systemPeriodMsToUs_gu64))
{
copySystemStepCounter_u64 = systemStepCounter_gu64;
tickValue_u64 = (uint64)(SysTick->VAL);
timeUs_u64 = copySystemStepCounter_u64 * systemPeriodMsToUs_gu64;
timeUs_u64 += ((systemTickLoadValue_gu64 - tickValue_u64) * systemPeriodMsToUs_gu64) / systemTickLoadValue_gu64;
/* The timer interruption is too fast, no time to process */
if(timeUs_u64 <= (uint64)(systemStepCounter_gu64 * systemPeriodMsToUs_gu64))
{
error_u32 = NMS_ERR_OVERRUN;
}
}
/* Should never happen if this timer interruption is set to highest priority */
if(copyPreviousTimeUs_u64 > timeUs_u64)
{
error_u32 = NMS_ERR_UNKNOWN;
}
else
{
*resultUs_pu64 = previousTimeUs_u64;
}
/* This condition has been added to prevent trouble overflow with interruptions
on the medium and high optimizations options */
*resultUs_pu64 = (timeUs_u64 > previousTimeUs_u64) ? timeUs_u64 : *resultUs_pu64;
return error_u32;
}
/* This function should not call the log, since it uses the system runtime. */
uint32 HalSystemGetRunTimeMs(uint64 * resultMs_pu64)
{
*resultMs_pu64 = systemStepCounter_gu64;
return NMS_ERR_NONE;
}
void HalSystemGetSerialId(uint8 * serialIdBuffer_pu8)
{
uint32 serialIdW0_u32, serialIdW1_u32, serialIdW2_u32;
/* Get the three parts of the UID */
serialIdW0_u32 = HAL_GetUIDw0();
serialIdW1_u32 = HAL_GetUIDw1();
serialIdW2_u32 = HAL_GetUIDw2();
/* Copy the values into the serial ID buffer */
memcpy(&serialIdBuffer_pu8[0], &serialIdW0_u32, sizeof(serialIdW0_u32));
memcpy(&serialIdBuffer_pu8[4], &serialIdW1_u32, sizeof(serialIdW1_u32));
memcpy(&serialIdBuffer_pu8[8], &serialIdW2_u32, sizeof(serialIdW2_u32));
}
uint32 HalSystemGetResetCause( HalSystemResetCauseEn resetCauseSelector_en, uint32 * causes_pu32 )
{
uint32 error_u32 = NMS_ERR_DEFAULT;
uint32 mask_u32 = 0uL;
if (causes_pu32 == NULL)
{
error_u32 = NMS_ERR_NULL_POINTER;
}
else
{
switch(resetCauseSelector_en)
{
case HAL_SYSTEM_RESET_CAUSE_OPTION_BYTE_LOADER:
mask_u32 = RCC_CSR_OBLRSTF_Msk;
error_u32 = NMS_ERR_NONE;
break;
case HAL_SYSTEM_RESET_CAUSE_EXTERNAL_PIN_RESET:
mask_u32 = RCC_CSR_PINRSTF_Msk;
error_u32 = NMS_ERR_NONE;
break;
case HAL_SYSTEM_RESET_CAUSE_BROWNOUT_RESET:
mask_u32 = RCC_CSR_BORRSTF_Msk;
error_u32 = NMS_ERR_NONE;
break;
case HAL_SYSTEM_RESET_CAUSE_SOFTWARE_RESET:
mask_u32 = RCC_CSR_SFTRSTF_Msk;
error_u32 = NMS_ERR_NONE;
break;
case HAL_SYSTEM_RESET_CAUSE_WATCH_DOG_TIMER:
mask_u32 = RCC_CSR_IWDGRSTF_Msk;
error_u32 = NMS_ERR_NONE;
break;
case HAL_SYSTEM_RESET_CAUSE_WINDOW_WATCH_DOG:
mask_u32 = RCC_CSR_WWDGRSTF_Msk;
error_u32 = NMS_ERR_NONE;
break;
case HAL_SYSTEM_RESET_CAUSE_LOW_POWER:
mask_u32 = RCC_CSR_LPWRRSTF_Msk;
error_u32 = NMS_ERR_NONE;
break;
case HAL_SYSTEM_RESET_CAUSE_ALL_CAUSES:
mask_u32 = RCC_CSR_IWDGRSTF_Msk
| RCC_CSR_WWDGRSTF_Msk
| RCC_CSR_SFTRSTF_Msk
| RCC_CSR_PINRSTF_Msk
| RCC_CSR_LPWRRSTF_Msk
| RCC_CSR_BORRSTF_Msk;
error_u32 = NMS_ERR_NONE;
break;
default:
error_u32 = NMS_ERR_UNKNOWN;
break;
}
*causes_pu32 = resetStatusRegister_gu32 & mask_u32;
}
return error_u32;
}
void HalSystemDisableInterrupts(void)
{
__disable_irq();
}
void HalSystemEnableInterrupts(void)
{
__enable_irq();
}
void HalSystemReset(void)
{
HAL_NVIC_SystemReset();
}
/******************************************************************************
* Callback Function Definitions
******************************************************************************/
/**
* @brief Count the number of milliseconds that elapsed since the start
*
* @note Function called by low-level functions of cubeMX
*/
void HAL_IncTick(void)
{
systemStepCounter_gu64++;
}
/**
* @brief Provides a tick value in millisecond.
*
* @return The number of elapsed tick.
*/
uint32 HAL_GetTick(void)
{
return (uint32)systemStepCounter_gu64;
}

View File

@ -1,114 +0,0 @@
/**
* @file hal_system.h
* @copyright Nehemis SARL reserves all rights even in the event of industrial
* property rights. We reserve all rights of disposal such as
* copying and passing on to third parties.
*
*
* @brief Header file for HAL layer for the SYSTEM module.
*
*/
#ifndef INCLUDED_HAL_SYSTEM_H
#define INCLUDED_HAL_SYSTEM_H
/******************************************************************************
* Include Header Files
******************************************************************************/
#include "nms_types.h"
/******************************************************************************
* Macros Constant Declarations
******************************************************************************/
#define SERIAL_ID_BUFFER_SIZE 12
/******************************************************************************
* Types Declarations
******************************************************************************/
typedef enum
{
HAL_SYSTEM_RESET_CAUSE_OPTION_BYTE_LOADER,
HAL_SYSTEM_RESET_CAUSE_EXTERNAL_PIN_RESET,
HAL_SYSTEM_RESET_CAUSE_BROWNOUT_RESET,
HAL_SYSTEM_RESET_CAUSE_SOFTWARE_RESET,
HAL_SYSTEM_RESET_CAUSE_WATCH_DOG_TIMER,
HAL_SYSTEM_RESET_CAUSE_WINDOW_WATCH_DOG,
HAL_SYSTEM_RESET_CAUSE_LOW_POWER,
HAL_SYSTEM_RESET_CAUSE_ALL_CAUSES
} HalSystemResetCauseEn; /**< Enumeration used to analyze the reset cause location. */
/******************************************************************************
* Global Variables Declarations
******************************************************************************/
/******************************************************************************
* Extern Functions Declarations
******************************************************************************/
/**
* @brief Initializes the system HAL.
*
* @note CAUTION: This function must be called immediately after
* SystemClock_Config() in the main function to ensure correct
* operation and prevent potential software issues.
*
* @return Error code: 0 if successful, nonzero otherwise.
*/
uint32 HalSystemInit(void);
/**
* @brief Retrieves the system runtime in microseconds.
*
* @param resultUs_pu64 Pointer to store the system runtime in microseconds.
*
* @note The tick resolution depends on the system tick frequency.
*
* @return Error code: 0 if successful, nonzero otherwise.
*/
uint32 HalSystemGetRunTimeUs(uint64 *resultUs_pu64);
/**
* @brief Retrieves the system runtime in milliseconds.
*
* @param resultMs_pu64 Pointer to store the system runtime in milliseconds.
*
* @note The tick resolution depends on the system tick frequency.
*
* @return Error code: 0 if successful, nonzero otherwise.
*/
uint32 HalSystemGetRunTimeMs(uint64 *resultMs_pu64);
/**
* @brief Disables all system interrupts.
*/
void HalSystemDisableInterrupts(void);
/**
* @brief Enables all system interrupts.
*/
void HalSystemEnableInterrupts(void);
/**
* @brief Retrieves the cause of the last system reset from the MCU registers.
*
* @param resetCauseSelector_en Enum specifying the reset cause type.
* causes_pu32 Pointer to store the corresponding bitmask value.
*
* @return Error code: 0 if successful, nonzero otherwise.
*/
uint32 HalSystemGetResetCause(HalSystemResetCauseEn resetCauseSelector_en, uint32 *causes_pu32);
/**
* @brief Retrieves the system's unique serial ID.
*
* @param serialIdBuffer_pu8 Pointer to the buffer where the serial ID will be stored.
*/
void HalSystemGetSerialId(uint8 *serialIdBuffer_pu8);
/**
* @brief Performs a software reset of the system.
*/
void HalSystemReset(void);
#endif /* INCLUDED_HAL_SYSTEM_H */

View File

@ -0,0 +1,574 @@
/**
* @file nms_can.c
*
* @copyright Nehemis SARL reserves all rights even in the event of industrial
* property rights. We reserve all rights of disposal such as
* copying and passing on to third parties.
*
* @brief Source code for CANOpen files abstracted for furthur use in the project.
*
*/
/******************************************************************************
* Include Header Files
******************************************************************************/
#include "nms_can.h"
#include "enduranceTestBench.h"
/* CANopen includes */
#include <gen_define.h>
#include <co_canopen.h>
#include "co_sdo.h"
#include "co_pdo.h"
#include "co_odaccess.h"
/******************************************************************************
* Global Variable Declaration
******************************************************************************/
/******************************************************************************
* Macro constant declarations
******************************************************************************/
#define NMS_CAN_CANOPEN_SLAVE_LINE 0u
#define NMS_CAN_CANOPEN_MASTER_LINE 1u
#define NMS_CAN_CANOPEN_BITRATE 250u
#define NMS_CAN_PU_MASTER_NODE_ID 1u
#define NMS_CAN_PU_SLAVE_NODE_ID 3u
#define NMS_CAN_LSS_TIMEOUT 20u /* Defined in stack examples */
#define NMS_CAN_LSS_CONFIG_TIMEOUT 1000u
#define NMS_CAN_LSS_CONFIG_INTERVAL 4u
#define NMS_CAN_APPL_TIMER_TIME 250000uL
#define NMS_CAN_LSS_NODE_COUNT 10u
#define NMS_CAN_LSS_NODE_HB_MS 1000uL
#define NMS_CAN_LSS_NODE_STATE_RESET_INTERVAL 3u
#define NMS_CAN_SDO_TRANSMIT 0x580u
#define NMS_CAN_SDO_RECEIVE 0x600u
#define NMS_CAN_SDO_PARAM_INDEX 0x1280u
#define NMS_LSS_NODE_COUNT 20u
/******************************************************************************
* Type Declarations
******************************************************************************/
typedef struct
{
uint32 vendorId_u32;
uint32 productId_u32;
uint32 versionNbr_u32;
uint32 serialNbr_u32;
uint8 nodeId_u8;
} SdlLssNodeInfo_t;
/******************************************************************************
* Global Declarations
******************************************************************************/
SdlLssNodeInfo_t var_gst;
static CO_TIMER_T monitorTimer_gst; /**< application timer */
static bool monitorSleep_gb = CO_FALSE; /**< sleep flag */
static bool masterStarted_gb; /**< master started flag */
static const SdlLssNodeInfo_t nodeLookupTable_gast[NMS_LSS_NODE_COUNT] =
{
{0x319, 0x4d2, 0x1, 0x01, 0x5} ,
{0x319, 0x4d2, 0x1, 0x02, 0x6} ,
{0x319, 0x4d2, 0x1, 0x03, 0x7} ,
{0x319, 0x4d2, 0x1, 0x04, 0x8} ,
{0x319, 0x4d2, 0x1, 0x05, 0x9} ,
{0x319, 0x4d2, 0x1, 0x06, 0xA} ,
{0x319, 0x4d2, 0x1, 0x07, 0xB} ,
{0x319, 0x4d2, 0x1, 0x08, 0xC} ,
{0x319, 0x4d2, 0x1, 0x09, 0xD} ,
{0x319, 0x4d2, 0x1, 0x0A, 0xE} ,
{0x319, 0x4d2, 0x1, 0x0B, 0xF} ,
{0x319, 0x4d2, 0x1, 0x0C, 0x10},
{0x319, 0x4d2, 0x1, 0x0D, 0x11},
{0x319, 0x4d2, 0x1, 0x0E, 0x12},
{0x319, 0x4d2, 0x1, 0x0F, 0x13},
{0x319, 0x4d2, 0x1, 0x10, 0x14},
{0x319, 0x4d2, 0x1, 0x11, 0x15},
{0x319, 0x4d2, 0x1, 0x12, 0x16},
{0x319, 0x4d2, 0x1, 0x13, 0x17},
{0x319, 0x4d2, 0x1, 0x14, 0x18}
};
static CO_NMT_STATE_T nodeNMTState_gaen[NMS_LSS_NODE_COUNT];
/******************************************************************************
* Private Function Definition
******************************************************************************/
static RET_T NmsCanOverwriteLoadIndication(uint8 index_u8);
static void NmsCanLssIndCallback( CO_LSS_MASTER_SERVICE_T service_en, uint16 errorCode_u16, uint8 errorSpec_u8, uint32 *pIdentity_pu32);
static void NmsCanLssHbMonitorCallback(uint8 nodeID_u8, CO_ERRCTRL_T state_en, CO_NMT_STATE_T nmtState_en);
static void NmsCanLssResetNodesCallback(void *pData_pv); /**< callback of reset handler */
static uint8 NmsCanLssGetNodeIndex(uint8 nodeId_u8);
static void NmsCanLssToggleMonitorFlag(void *pData_pv);
static void NmsCanLssNodeHandlerRun(void);
static uint32 NmsCanLssConfigureNode(uint8 arrIndex_u8);
static RET_T NmsCanLssSetSdoCobID(uint8 sdoNr_u8, uint8 nodeId_u8);
/* Supress warnings for implicit declaration.
* Need this function for overwriting the manual COB ids
* for the TPDO. */
extern void userOverwriteCobIdSettings(void);
/******************************************************************************
* Extern Function Declarations
******************************************************************************/
void NmsCanInit()
{
codrvHardwareInit();
codrvCanInit(NMS_CANOPEN_BITRATE);
codrvTimerSetup(CO_TIMER_INTERVAL);
/* CANopen Initialization */
coCanOpenStackInit(NmsCanOverwriteLoadIndication);
coEventRegister_LSS_MASTER(NmsCanLssIndCallback);
coEventRegister_ERRCTRL(NmsCanLssHbMonitorCallback);
/* Register SDO event handlers */
coEventRegister_SDO_CLIENT_READ(EnduranceTestBenchReadInd);
coEventRegister_SDO_CLIENT_WRITE(EnduranceTestBenchWriteInd);
/* enable CAN communication */
codrvCanEnable();
coTimerStart(&monitorTimer_gst, NMS_CAN_APPL_TIMER_TIME, NmsCanLssToggleMonitorFlag, NULL, CO_TIMER_ATTR_ROUNDUP_CYCLIC);
coLssIdentifyNonConfiguredSlaves(NMS_CAN_LSS_CONFIG_TIMEOUT, NMS_CAN_LSS_CONFIG_INTERVAL);
/* node == 0, the NMT request is sent to all nodes. */
coNmtStateReq(NMS_CAN_PU_MASTER_NODE_ID, CO_NMT_STATE_OPERATIONAL, CO_TRUE);
}
void NmsCanRun(void)
{
coCommTask();
/* LSS main runner */
NmsCanLssNodeHandlerRun();
}
uint32 NmsCanGetObj_u8(uint16 index_u16, uint8 subIndex_u8, uint8 *pObj_pu8)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
RET_T retVal_en = coOdGetObj_u8(index_u16, subIndex_u8, pObj_pu8);
if ( retVal_en == RET_OK)
{
error_u32 = NMS_ERR_NONE;
}
return error_u32;
}
uint32 NmsCanGetObj_u32(uint16 index_u16, uint8 subIndex_u8, uint32 *pObj_pu32)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
RET_T retVal_en = coOdGetObj_u32(index_u16, subIndex_u8, pObj_pu32);
if ( retVal_en == RET_OK)
{
error_u32 = NMS_ERR_NONE;
}
return error_u32;
}
uint32 NmsCanGetObj_f32(uint16 index_u16, uint8 subIndex_u8, float32 *pObj_pf32)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
RET_T retVal_en = coOdGetObj_r32(index_u16, subIndex_u8, pObj_pf32);
if ( retVal_en == RET_OK)
{
error_u32 = NMS_ERR_NONE;
}
return error_u32;
}
uint32 NmsCanPutObj_u8(uint16 index_u16, uint8 subIndex_u8, uint8 newVal_u8)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
RET_T retVal_en = coOdPutObj_u8(index_u16, subIndex_u8, newVal_u8);
if ( retVal_en == RET_OK)
{
error_u32 = NMS_ERR_NONE;
}
return error_u32;
}
uint32 NmsCanPutObj_u32(uint16 index_u16, uint8 subIndex_u8, uint32 newVal_u32)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
RET_T retVal_en = coOdPutObj_u32(index_u16, subIndex_u8, newVal_u32);
if ( retVal_en == RET_OK)
{
error_u32 = NMS_ERR_NONE;
}
return error_u32;
}
uint32 NmsCanPutObj_f32(uint16 index_u16, uint8 subIndex_u8, uint32 newVal_u32)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
RET_T retVal_en = coOdPutObj_r32(index_u16, subIndex_u8, newVal_u32);
if ( retVal_en == RET_OK)
{
error_u32 = NMS_ERR_NONE;
}
return error_u32;
}
/******************************************************************************
* Private Function Definitions
******************************************************************************/
/**
* @brief Handler for the defined nodes in the network.
* This function starts the configuration of a node if needed
*
* @return void
*
*/
static void NmsCanLssNodeHandlerRun(void)
{
if (monitorSleep_gb != CO_TRUE)
{
for (uint8 i_u8 = 0u; i_u8 < NMS_CAN_LSS_NODE_COUNT; i_u8++)
{
if (nodeNMTState_gaen[i_u8] == CO_NMT_STATE_PREOP)
{
NmsCanLssConfigureNode(i_u8);
}
if (nodeNMTState_gaen[i_u8] == CO_NMT_STATE_OPERATIONAL)
{
/* Do nothing */
}
}
}
monitorSleep_gb = CO_TRUE;
}
/**
* @brief Load function for overwriting the TPDO COB id values.
*
* @param index_u8 Subindex parameter to point parameter area(unused)
* canLine_u8 The canline MASTER or SLAVE
*
* @return Error Code
*/
static RET_T NmsCanOverwriteLoadIndication(uint8 index_u8)
{
userOverwriteCobIdSettings();
return RET_OK;
}
/**
* @brief This function is called if a new NMT state of a node,
* is recordnized by the CANopen stack.
*
* @param nodeID_u8 Node id of the node that has registered a change.
* state_en Error control state
* nmtState_en NMT state of the particular node.
*
* @return Array index of the node in the network.
*
*/
static uint8 NmsCanLssGetNodeIndex(uint8 nodeId_u8)
{
uint8 arrIndex_u8;
/* find node ID array arrIndex_u8 */
for (arrIndex_u8 = 0u; arrIndex_u8 < NMS_CAN_LSS_NODE_COUNT; arrIndex_u8++)
{
if (nodeId_u8 == nodeLookupTable_gast[arrIndex_u8].nodeId_u8)
{
return arrIndex_u8;
}
}
return NMS_UINT8_MAX;
}
/**
* @brief This function is called when a new NMT state of a node
* is recognized by the CANopen stack.
*
* @param canLine_u8 Indicates whether the node is on the MASTER or SLAVE CAN line.
* pData Pointer to additional data (unused).
*/
static void NmsCanLssToggleMonitorFlag(void *pData_pv)
{
(void)pData_pv;
/* deactivate application sleep flag */
monitorSleep_gb = CO_FALSE;
}
/**
* @brief Configure a specific node.
* This function adds the defined node to heartbeat consumers,
* and sets its heartbeat interval.
*
* @param arrIndex_u8 Index of the node in the array which is to be configured.
*
* @return Status of the operation.
*
*/
static uint32 NmsCanLssConfigureNode(uint8 arrIndex_u8)
{
uint32 error_u32 = NMS_ERR_DEFAULT;
RET_T retVal_en = RET_INTERNAL_ERROR;
/* Get the node ID from the lookup table using arrIndex_u8 */
uint8 nodeId_u8 = nodeLookupTable_gast[arrIndex_u8].nodeId_u8;
/* Add node to hb consumers with +25% tolerance
* Rationale - Allows some flexibility in detecting timeouts due to minor clock drifts,
* bus delays, or transmission issues.*/
retVal_en = coHbConsumerSet(nodeId_u8,
((NMS_CAN_LSS_NODE_HB_MS / 100 * 25) + NMS_CAN_LSS_NODE_HB_MS));
retVal_en = coHbConsumerStart(nodeId_u8);
/* setup SDO channel */
retVal_en = NmsCanLssSetSdoCobID((arrIndex_u8 + 1), nodeLookupTable_gast[arrIndex_u8].nodeId_u8);
//retVal_en = coSdoWrite(NmsCan_CANOPEN_MASTER_LINE, (arrIndex_u8 + 1), 0x1017u, 0u, (uint8*)(&nodeHBs[0]), 2u, CO_FALSE, 1000u);
/* start node */
retVal_en = coNmtStateReq(nodeId_u8, CO_NMT_STATE_OPERATIONAL, CO_FALSE);
if (retVal_en != RET_OK)
{
error_u32 = NMS_LSS_NODE_CONFIG_ERROR;
}
/* set local state to operational, if not operational yet */
if (masterStarted_gb == CO_FALSE)
{
/* set local state */
coNmtLocalStateReq(CO_NMT_STATE_OPERATIONAL);
/* save started flag */
masterStarted_gb = CO_TRUE;
}
return error_u32;
}
/******************************************************************************
* Callback Function Definitions
******************************************************************************/
/**
* @brief LSS indication function for handling the LSS api calls for dynamic
* setup of node ids.
*
* @param canLine_u8 The canline MASTER or SLAVE
* service_en LSS master services for indication functions
* errorCode_u16 Error code in the module
* errorSpec_u8 Specific error case that has occured
* pIdentity_pu32 LSS slave identity.
*
*/
static void NmsCanLssIndCallback(CO_LSS_MASTER_SERVICE_T service_en, uint16 errorCode_u16, uint8 errorSpec_u8, uint32 *pIdentity_pu32)
{
static uint8 matchedIndex_u8 = NMS_UINT8_MAX;
if (errorCode_u16 != 0u)
{
if (errorCode_u16 == NMS_UINT16_MAX)
{
/* ERROR */
}
else
{
/* ERROR */
}
if (service_en == CO_LSS_MASTER_SERVICE_STORE)
{
/* DEBUG INFO */
coLssSwitchGlobal(CO_LSS_STATE_WAITING);
}
return;
}
switch (service_en)
{
case CO_LSS_MASTER_SERVICE_NON_CONFIG_SLAVE:
/* DEBUG INFO */
coLssFastScan(NMS_CAN_LSS_TIMEOUT);
break;
case CO_LSS_MASTER_SERVICE_FASTSCAN:
/* Match detected node with lookup table */
for (uint8 i_u8 = 0; i_u8 < NMS_CAN_LSS_NODE_COUNT; i_u8++)
{
if (pIdentity_pu32[0] == nodeLookupTable_gast[i_u8].vendorId_u32 &&
pIdentity_pu32[1] == nodeLookupTable_gast[i_u8].productId_u32 &&
pIdentity_pu32[2] == nodeLookupTable_gast[i_u8].versionNbr_u32 &&
pIdentity_pu32[3] == nodeLookupTable_gast[i_u8].serialNbr_u32)
{
coLssSwitchSelective(pIdentity_pu32[0], pIdentity_pu32[1],
pIdentity_pu32[2], pIdentity_pu32[3], 20);
matchedIndex_u8 = i_u8;
break;
}
}
break;
case CO_LSS_MASTER_SERVICE_SWITCH_SELECTIVE:
if (matchedIndex_u8 < NMS_CAN_LSS_NODE_COUNT)
{
coLssSetNodeId(nodeLookupTable_gast[matchedIndex_u8].nodeId_u8, NMS_CAN_LSS_TIMEOUT);
matchedIndex_u8 = NMS_UINT8_MAX;
}
else
{
/* ERROR */
}
break;
case CO_LSS_MASTER_SERVICE_SET_NODEID:
/* DEBUG INFO */
coLssInquireNodeId(NMS_CAN_LSS_TIMEOUT);
break;
case CO_LSS_MASTER_SERVICE_INQUIRE_NODEID:
/* DEBUG INFO */
coLssStoreConfig( 200);
break;
case CO_LSS_MASTER_SERVICE_STORE:
/* DEBUG INFO */
coLssSwitchGlobal(CO_LSS_STATE_WAITING);
break;
default:
/* ERROR */
break;
}
}
/**
* @brief This function is called if a new NMT state of a node,
* is recordnized by the CANopen stack.
*
* @param nodeID_u8 Node id of the node that has registered a change.
* state_en Error control state
* nmtState_en NMT state of the particular node.
*
* @return void
*
*/
static void NmsCanLssHbMonitorCallback(uint8 nodeID_u8, CO_ERRCTRL_T state_en, CO_NMT_STATE_T nmtState_en)
{
uint8 arrIndex_u8;
/* look if node is monitored */
arrIndex_u8 = NmsCanLssGetNodeIndex(nodeID_u8);
/* handle monitored node */
if (arrIndex_u8 != NMS_UINT16_MAX)
{
/* save states */
nodeNMTState_gaen[arrIndex_u8] = nmtState_en;
/* indicate if monitored node lost heartbeat */
if (nmtState_en == CO_NMT_STATE_UNKNOWN)
{
/* To be transmitted via CAN */
/* ERROR */
}
/* indicate if monitored node sent a bootup message */
if (state_en == CO_ERRCTRL_BOOTUP)
{
/* INFO */
}
/* handle unmonitored node */
}
else
{
/* ERROR */
}
}
/**
* @brief This function tries to reset nodes with unknown NMT state.
*
* @param pData_pv Data.
*/
static void NmsCanLssResetNodesCallback(void *pData_pv)
{
uint8 arrIndex_u8;
(void)pData_pv;
/* reset defined nodes without known state */
for (arrIndex_u8 = 0u; arrIndex_u8 < 3; arrIndex_u8++)
{
if ((nodeNMTState_gaen[arrIndex_u8] != CO_NMT_STATE_PREOP) &&
(nodeNMTState_gaen[arrIndex_u8] != CO_NMT_STATE_OPERATIONAL))
{
/* reset node */
coNmtStateReq(nodeLookupTable_gast[arrIndex_u8].nodeId_u8, CO_NMT_STATE_RESET_NODE, CO_FALSE);
}
}
}
/**
* @brief This function configures a SDO client for the
* given node ID and SDO number.
*
* @param sdoNr_u8 Sdo number
* nodeId_u8 Node id of the node.
*
* @return Error state.
*
*/
static RET_T NmsCanLssSetSdoCobID(uint8 sdoNr_u8, uint8 nodeId_u8)
{
uint16 cobIndex_u16;
uint32 newCobId_u32;
RET_T retVal = RET_INTERNAL_ERROR;
/* get od index of sdoNr */
cobIndex_u16 = NMS_CAN_SDO_PARAM_INDEX + sdoNr_u8 - 1u;
/* set cobID for client to server direction (request) */
newCobId_u32 = NMS_CAN_SDO_RECEIVE + nodeId_u8;
retVal = coOdSetCobid(cobIndex_u16, 1u, newCobId_u32);
if (retVal == RET_OK)
{
/* set cobID for server to client direction (response) */
newCobId_u32 = NMS_CAN_SDO_TRANSMIT + nodeId_u8;
retVal = coOdSetCobid(cobIndex_u16, 2u, newCobId_u32);
}
/* print failed setup details */
if (retVal != RET_OK)
{
/* ERROR */
}
return retVal;
}

View File

@ -0,0 +1,108 @@
/**
* @file nms_can.h
*
* @copyright Nehemis SARL reserves all rights even in the event of industrial
* property rights. We reserve all rights of disposal such as
* copying and passing on to third parties.
*
* @brief CANOpen files abstracted for furthur use in the project.
*
*/
#ifndef NMS_CAN_H_
#define NMS_CAN_H_
/******************************************************************************
* Include Header Files
******************************************************************************/
#include "nms_types.h"
#include "co_datatype.h"
#include "co_nmt.h"
/******************************************************************************
* Macro constant declarations
******************************************************************************/
#define NMS_CANOPEN_BITRATE 250u
/******************************************************************************
* Extern Function Declarations
******************************************************************************/
/**
* @brief Initializes the CAN controller and CANopen stack.
*/
void NmsCanInit(void);
/**
* @brief Runs the CAN communication tasks.
*
* @param canLine_u8 Can line selected.
*/
void NmsCanRun(void);
/**
* @brief Retrieves a 8-bit object from the CANopen object dictionary.
*
* @param index_u16 The object dictionary index.
* subIndex_u8 The sub-index of the object.
* pObj_pu8 Pointer to store the retrieved object value.
* canLine_u8 Can line selected.
*
* @return Error code. (NMS_ERR_NONE if successful, or an error code).
*/
uint32 NmsCanGetObj_u8(uint16 index_u16, uint8 subIndex_u8, uint8 *pObj_pu8);
/**
* @brief Retrieves a 32-bit object from the CANopen object dictionary.
*
* @param index_u16 The object dictionary index.
* subIndex_u8 The sub-index of the object.
* pObj_pu8 Pointer to store the retrieved object value.
*
* @return Error code. (NMS_ERR_NONE if successful, or an error code).
*/
uint32 NmsCanGetObj_u32(uint16 index_u16, uint8 subIndex_u8, uint32 *pObj_pu32);
/**
* @brief Retrieves a float object from the CANopen object dictionary.
*
* @param index_u16 The object dictionary index.
* subIndex_u8 The sub-index of the object.
* pObj_f32 Pointer to store the retrieved object value.
*
* @return Error code. (NMS_ERR_NONE if successful, or an error code).
*/
uint32 NmsCanGetObj_f32(uint16 index_u16, uint8 subIndex_u8, float32 *pObj_pf32);
/**
* @brief Puts a 8-bit object in the CANopen object dictionary.
*
* @param index_u16 The object dictionary index.
* subIndex_u8 The sub-index of the object.
* newVal_u32 The new value to be set.
*
* @return Error code. (NMS_ERR_NONE if successful, or an error code).
*/
uint32 NmsCanPutObj_u8(uint16 index_u16, uint8 subIndex_u8, uint8 newVal_u8);
/**
* @brief Puts a 32-bit object in the CANopen object dictionary.
*
* @param index_u16 The object dictionary index.
* subIndex_u8 The sub-index of the object.
* newVal_u32 The new value to be set.
*
* @return Error code. (NMS_ERR_NONE if successful, or an error code).
*/
uint32 NmsCanPutObj_u32(uint16 index_u16, uint8 subIndex_u8, uint32 newVal_u32);
/**
* @brief Puts a float object in the CANopen object dictionary.
*
* @param index_u16 The object dictionary index.
* subIndex_u8 The sub-index of the object.
* newVal_u32 The new value to be set.
*
* @return Error code. (NMS_ERR_NONE if successful, or an error code).
*/
uint32 NmsCanPutObj_f32(uint16 index_u16, uint8 subIndex_u8, uint32 newVal_u32);
#endif /* NMS_CAN_H_ */

View File

@ -17,105 +17,29 @@
/******************************************************************************
* Include Header Files
******************************************************************************/
/* CANopen includes */
#include <co_canopen.h>
#include <gen_define.h>
#include <co_canopen.h>
#include "co_sdo.h"
#include "co_odaccess.h"
/* User includes */
#include "sdl.h"
#include "nms_can.h"
#include "processBoard.h"
#include "enduranceTestBench.h"
#include "hal_system.h"
#include "stdlib.h"
#include "hal_system.h"
/******************************************************************************
* Macro constant declarations
******************************************************************************/
#define SDL_CANOPEN_BITRATE 250u
#define SDL_PU_MASTER_NODE_ID 1u
#define SDL_LSS_TIMEOUT 20u /* Defined in stack examples */
#define SDL_LSS_CONFIG_TIMEOUT 1000u
#define SDL_LSS_CONFIG_INTERVAL 4u
#define SDL_APPL_TIMER_TIME 250000uL
#define SDL_LSS_NODE_COUNT 20u
#define SDL_LSS_NODE_HB_MS 1000uL
#define SDL_LSS_NODE_STATE_RESET_INTERVAL 3u
#define SDL_TEST_BENCH_SDO_TIMEOUT 1000u
#define SDL_TEST_BENCH_STARTUP_TIMEOUT 10000uLL
#define SDL_POSITION_SETPOINT_INDEX 0x6002
#define SDL_POSITION_SETPOINT_SUB_INDEX 0x0
#define SDL_POSITION_FEEDBACK_INDEX 0x6004
#define SDL_POSITION_FEEDBACK_SUB_INDEX 0x0
#define SDL_SDO_CLIENT_COB 0x1280
#define SDL_SDO_CLIENT_TO_SERVER_COB 0x600
#define SDL_SDO_SERVER_TO_CLIENT_COB 0x580
#define SDL_MIN_OPERATIONAL_NODES 18u /* To be 20, one node not in working state currently */
#define SDL_LSS_NODE_COUNT 20u
/******************************************************************************
* Type Declarations
******************************************************************************/
typedef struct
{
uint32 vendorId_u32;
uint32 productId_u32;
uint32 versionNbr_u32;
uint32 serialNbr_u32;
uint8 nodeId_u8;
} SdlLssNodeInfo_t;
/******************************************************************************
* Global Declarations
******************************************************************************/
SdlLssNodeInfo_t var_gst;
static CO_TIMER_T monitorTimer_gst; /**< application timer */
static CO_TIMER_T nodeResetTimer_gst; /**< node reset timer */
static bool monitorSleep_gb = CO_FALSE; /**< sleep flag */
static bool masterStarted_gb; /**< master started flag */
static const SdlLssNodeInfo_t nodeLookupTable_gast[SDL_LSS_NODE_COUNT] =
{
{0x319, 0x4d2, 0x1, 0x01, 0x5} ,
{0x319, 0x4d2, 0x1, 0x02, 0x6} ,
{0x319, 0x4d2, 0x1, 0x03, 0x7} ,
{0x319, 0x4d2, 0x1, 0x04, 0x8} ,
{0x319, 0x4d2, 0x1, 0x05, 0x9} ,
{0x319, 0x4d2, 0x1, 0x06, 0xA} ,
{0x319, 0x4d2, 0x1, 0x07, 0xB} ,
{0x319, 0x4d2, 0x1, 0x08, 0xC} ,
{0x319, 0x4d2, 0x1, 0x09, 0xD} ,
{0x319, 0x4d2, 0x1, 0x0A, 0xE} ,
{0x319, 0x4d2, 0x1, 0x0B, 0xF} ,
{0x319, 0x4d2, 0x1, 0x0C, 0x10},
{0x319, 0x4d2, 0x1, 0x0D, 0x11},
{0x319, 0x4d2, 0x1, 0x0E, 0x12},
{0x319, 0x4d2, 0x1, 0x0F, 0x13},
{0x319, 0x4d2, 0x1, 0x10, 0x14},
{0x319, 0x4d2, 0x1, 0x11, 0x15},
{0x319, 0x4d2, 0x1, 0x12, 0x16},
{0x319, 0x4d2, 0x1, 0x13, 0x17},
{0x319, 0x4d2, 0x1, 0x14, 0x18}
};
static CO_NMT_STATE_T nodeNMTState_gaen[SDL_LSS_NODE_COUNT];
/******************************************************************************
* Static function Declarations
******************************************************************************/
static void SdlInitCanopen(void);
static void SdlRunCanopen(void);
static RET_T SdlOverwriteLoadIndication(uint8 index_u8);
static void SdlLssIndCallback(CO_LSS_MASTER_SERVICE_T service_en, uint16 errorCode_u16, uint8 errorSpec_u8, uint32 *pIdentity_pu32);
static void SdlLssHbMonitorCallback(uint8 nodeID_u8, CO_ERRCTRL_T state_en, CO_NMT_STATE_T nmtState_en);
static void SdlLssResetNodesCallback(void *pData_pv); /**< callback of reset handler */
static uint8 SdlLssGetNodeIndex(uint8 nodeId_u8);
static void SdlLssToggleMonitorFlag(void *pData);
static void SdlLssNodeHandlerRun(void);
static uint32 SdlLssConfigureNode(uint8 arrIndex_u8);
static RET_T SdlLssSetSdoCobID(uint8 sdoNr_u8, uint8 nodeId_u8);
/* Supress warnings for implicit declaration.
* Need this function for overwriting the manual COB ids
* for the TPDO. */
@ -127,246 +51,24 @@ static bool SdlAreAllNodesOperational(void);
******************************************************************************/
void SdlInit(void)
{
SdlInitCanopen();
HalSystemInit();
NmsCanInit();
}
void SdlRun(void)
{
SdlRunCanopen();
SdlLssNodeHandlerRun();
NmsCanRun();
if (SdlAreAllNodesOperational())
{
EnduranceTestBenchRun();
ProcessBoardRun();
}
}
/******************************************************************************
* Private Function Declarations
******************************************************************************/
/**
* @brief Init the CANopen stack.
*
*/
static void SdlInitCanopen(void)
{
RET_T retval;
HalSystemInit();
codrvHardwareInit();
retval = codrvCanInit(SDL_CANOPEN_BITRATE);
retval = codrvTimerSetup(CO_TIMER_INTERVAL);
/* CANopen Initialization */
retval = coCanOpenStackInit(SdlOverwriteLoadIndication);
retval = coEventRegister_LSS_MASTER(SdlLssIndCallback);
retval = coEventRegister_ERRCTRL(SdlLssHbMonitorCallback);
/* Register SDO event handlers */
coEventRegister_SDO_CLIENT_READ(EnduranceTestBenchReadInd);
coEventRegister_SDO_CLIENT_WRITE(EnduranceTestBenchWriteInd);
/* enable CAN communication */
retval = codrvCanEnable();
retval = coTimerStart(&monitorTimer_gst, SDL_APPL_TIMER_TIME, SdlLssToggleMonitorFlag, NULL, CO_TIMER_ATTR_ROUNDUP_CYCLIC);
//retval = coTimerStart(&nodeResetTimer_gst, (SDL_LSS_NODE_STATE_RESET_INTERVAL * 1000000uLL), SdlLssResetNodesCallback, NULL, CO_TIMER_ATTR_ROUNDUP_CYCLIC);
coLssIdentifyNonConfiguredSlaves(SDL_LSS_CONFIG_TIMEOUT, SDL_LSS_CONFIG_INTERVAL);
retval = coNmtStateReq(SDL_PU_MASTER_NODE_ID, CO_NMT_STATE_OPERATIONAL, CO_TRUE);
}
/**
* @brief Runs the CANopen stack.
*
*/
static void SdlRunCanopen(void)
{
coCommTask();
SdlLssNodeHandlerRun();
}
/******************************************************************************
* Private Function Definitions
******************************************************************************/
/**
* @brief Handler for the defined nodes in the network.
* This function starts the configuration of a node if needed
*
* @return void
*
*/
static void SdlLssNodeHandlerRun(void)
{
if (monitorSleep_gb != CO_TRUE)
{
for (uint8 i_u8 = 0u; i_u8 < SDL_LSS_NODE_COUNT; i_u8++)
{
if (nodeNMTState_gaen[i_u8] == CO_NMT_STATE_PREOP)
{
SdlLssConfigureNode(i_u8);
}
if (nodeNMTState_gaen[i_u8] == CO_NMT_STATE_OPERATIONAL)
{
/* Do nothing */
}
}
}
monitorSleep_gb = CO_TRUE;
}
/**
* @brief Load function for overwriing the TPDO COB id values.
*
* @param index_u8 Subindex parameter to point parameter area(unused)
*
* @return Error Code
*/
static RET_T SdlOverwriteLoadIndication(uint8 index_u8)
{
userOverwriteCobIdSettings();
return RET_OK;
}
/**
* @brief This function is called if a new NMT state of a node,
* is recordnized by the CANopen stack.
*
* @param nodeID_u8 Node id of the node that has registered a change.
* state_en Error control state
* nmtState_en NMT state of the particular node.
*
* @return Array index of the node in the network.
*
*/
static uint8 SdlLssGetNodeIndex(uint8 nodeId_u8)
{
uint8 arrIndex_u8;
/* find node ID array arrIndex_u8 */
for (arrIndex_u8 = 0u; arrIndex_u8 < SDL_LSS_NODE_COUNT; arrIndex_u8++)
{
if (nodeId_u8 == nodeLookupTable_gast[arrIndex_u8].nodeId_u8)
{
return arrIndex_u8;
}
}
return NMS_UINT8_MAX;
}
/**
* @brief This function is called if a new NMT state of a node,
* is recordnized by the CANopen stack.
*
* @param nodeID_u8 Node id of the node that has registered a change.
* state_en Error control state
* nmtState_en NMT state of the particular node.
*
* @return Array index of the node in the network.
*
*/
static void SdlLssToggleMonitorFlag(void *pData)
{
(void)pData;
/* deactivate application sleep flag */
monitorSleep_gb = CO_FALSE;
}
/**
* @brief Configure a specific node.
* This function adds the defined node to heartbeat consumers,
* and sets its heartbeat interval.
*
* @param arrIndex_u8 Index of the node in the array which is to be configured.
*
* @return Status of the operation.
*
*/
static uint32 SdlLssConfigureNode(uint8 arrIndex_u8)
{
uint32 error_u32 = SDL_DEFAULT_ERROR;
RET_T retVal_en = RET_INTERNAL_ERROR;
/* Get the node ID from the lookup table using the index passed */
uint8 nodeId_u8 = nodeLookupTable_gast[arrIndex_u8].nodeId_u8;
/* Add node to heartbeat consumers with +25% tolerance
* Rationale - Allows some flexibility in detecting timeouts due to minor clock drifts,
* bus delays, or transmission issues.*/
retVal_en = coHbConsumerSet(nodeId_u8,
((SDL_LSS_NODE_HB_MS / 100u * 25u) + SDL_LSS_NODE_HB_MS));
retVal_en = coHbConsumerStart(nodeId_u8);
/* setup SDO channel */
retVal_en = SdlLssSetSdoCobID((arrIndex_u8 + 1u), nodeLookupTable_gast[arrIndex_u8].nodeId_u8);
/* start node */
retVal_en = coNmtStateReq(nodeId_u8, CO_NMT_STATE_OPERATIONAL, CO_FALSE);
if (retVal_en != RET_OK)
{
error_u32 = SDL_LSS_NODE_CONFIG_ERROR;
}
/* set local state to operational, if not operational yet */
if (masterStarted_gb == CO_FALSE)
{
/* set local state */
coNmtLocalStateReq(CO_NMT_STATE_OPERATIONAL);
/* save started flag */
masterStarted_gb = CO_TRUE;
}
return error_u32;
}
/**
* @brief This function configures a SDO client for the
* given node ID and SDO number.
*
* @param sdoNr_u8 Sdo number
* nodeId_u8 Node id of the node.
*
* @return Error state.
*
*/
static RET_T SdlLssSetSdoCobID(uint8 sdoNr_u8, uint8 nodeId_u8)
{
uint16 cobIndex_u16;
uint32 newCobId_u32;
RET_T retVal_en = RET_INTERNAL_ERROR;
/* get od index of sdoNr */
cobIndex_u16 = SDL_SDO_CLIENT_COB + sdoNr_u8 - 1u; /* SDO starts from 1280 index */
/* set cobID for client to server direction (request) */
newCobId_u32 = SDL_SDO_CLIENT_TO_SERVER_COB + nodeId_u8;
retVal_en = coOdSetCobid(cobIndex_u16, 1u, newCobId_u32);
if (retVal_en == RET_OK)
{
/* set cobID for server to client direction (response) */
newCobId_u32 = SDL_SDO_SERVER_TO_CLIENT_COB + nodeId_u8;
retVal_en = coOdSetCobid(cobIndex_u16, 2u, newCobId_u32);
}
/* print failed setup details */
if (retVal_en != RET_OK)
{
/* ERROR */
}
return retVal_en;
}
/**
* @brief Checks if all nodes are in OPERATIONAL state.
@ -387,166 +89,3 @@ static bool SdlAreAllNodesOperational(void)
return (operationalNodeNb_u8 >= SDL_MIN_OPERATIONAL_NODES) ? CO_TRUE : CO_FALSE;
}
/******************************************************************************
* Callback Function Definitions
******************************************************************************/
/**
* @brief LSS indication function for handling the LSS api calls for dynamic
* setup of node ids.
*
* @param service_en LSS master services for indication functions
* errorCode_u16 Error code in the module
* errorSpec_u8 Specific error case that has occured
* pIdentity_pu32 LSS slave identity.
*
*/
static void SdlLssIndCallback(CO_LSS_MASTER_SERVICE_T service_en, uint16 errorCode_u16, uint8 errorSpec_u8, uint32 *pIdentity_pu32)
{
static uint8 matchedIndex_u8 = NMS_UINT8_MAX;
if (errorCode_u16 != 0u)
{
if (errorCode_u16 == NMS_UINT16_MAX)
{
/* ERROR */
}
else
{
/* ERROR */
}
if (service_en == CO_LSS_MASTER_SERVICE_STORE)
{
/* DEBUG INFO */
coLssSwitchGlobal(CO_LSS_STATE_WAITING);
}
return;
}
switch (service_en)
{
case CO_LSS_MASTER_SERVICE_NON_CONFIG_SLAVE:
/* DEBUG INFO */
coLssFastScan(SDL_LSS_TIMEOUT);
break;
case CO_LSS_MASTER_SERVICE_FASTSCAN:
/* Match detected node with lookup table */
for (uint8 i_u8 = 0u; i_u8 < SDL_LSS_NODE_COUNT; i_u8++)
{
if (pIdentity_pu32[0] == nodeLookupTable_gast[i_u8].vendorId_u32 &&
pIdentity_pu32[1] == nodeLookupTable_gast[i_u8].productId_u32 &&
pIdentity_pu32[2] == nodeLookupTable_gast[i_u8].versionNbr_u32 &&
pIdentity_pu32[3] == nodeLookupTable_gast[i_u8].serialNbr_u32)
{
coLssSwitchSelective(pIdentity_pu32[0], pIdentity_pu32[1],
pIdentity_pu32[2], pIdentity_pu32[3], 20);
matchedIndex_u8 = i_u8;
break;
}
}
break;
case CO_LSS_MASTER_SERVICE_SWITCH_SELECTIVE:
if (matchedIndex_u8 < SDL_LSS_NODE_COUNT)
{
coLssSetNodeId(nodeLookupTable_gast[matchedIndex_u8].nodeId_u8, SDL_LSS_TIMEOUT);
matchedIndex_u8 = NMS_UINT8_MAX;
}
else
{
/* ERROR */
}
break;
case CO_LSS_MASTER_SERVICE_SET_NODEID:
/* DEBUG INFO */
coLssInquireNodeId(SDL_LSS_TIMEOUT);
break;
case CO_LSS_MASTER_SERVICE_INQUIRE_NODEID:
/* DEBUG INFO */
coLssStoreConfig(200);
break;
case CO_LSS_MASTER_SERVICE_STORE:
/* DEBUG INFO */
coLssSwitchGlobal(CO_LSS_STATE_WAITING);
break;
default:
/* ERROR */
break;
}
}
/**
* @brief This function is called if a new NMT state of a node,
* is recordnized by the CANopen stack.
*
* @param nodeID_u8 Node id of the node that has registered a change.
* state_en Error control state
* nmtState_en NMT state of the particular node.
*
* @return void
*
*/
static void SdlLssHbMonitorCallback(uint8 nodeID_u8, CO_ERRCTRL_T state_en, CO_NMT_STATE_T nmtState_en)
{
uint8 arrIndex_u8;
/* look if node is monitored */
arrIndex_u8 = SdlLssGetNodeIndex(nodeID_u8);
/* handle monitored node */
if (arrIndex_u8 != NMS_UINT16_MAX)
{
/* save states */
nodeNMTState_gaen[arrIndex_u8] = nmtState_en;
/* indicate if monitored node lost heartbeat */
if (nmtState_en == CO_NMT_STATE_UNKNOWN)
{
/* To be transmitted via CAN */
/* ERROR */
}
/* indicate if monitored node sent a bootup message */
if (state_en == CO_ERRCTRL_BOOTUP)
{
/* INFO */
}
/* handle unmonitored node */
}
else
{
/* ERROR */
}
}
/**
* @brief This function tries to reset nodes with unknown NMT state.
*
* @param pData_pv Data.
*/
static void SdlLssResetNodesCallback(void *pData_pv)
{
uint8 arrIndex_u8;
(void)pData_pv;
/* reset defined nodes without known state */
for (arrIndex_u8 = 0u; arrIndex_u8 < SDL_LSS_NODE_COUNT; arrIndex_u8++)
{
if ((nodeNMTState_gaen[arrIndex_u8] != CO_NMT_STATE_PREOP) &&
(nodeNMTState_gaen[arrIndex_u8] != CO_NMT_STATE_OPERATIONAL))
{
/* reset node */
coNmtStateReq(nodeLookupTable_gast[arrIndex_u8].nodeId_u8, CO_NMT_STATE_RESET_NODE, CO_FALSE);
}
}
}

View File

@ -76,7 +76,10 @@ typedef enum
NMS_ERR_NOT_INITIALIZED, /* The initialization was unsuccessful */
NMS_ERR_NOT_RUNNING, /* Module has not been started */
NMS_ERR_BUS_ERROR, /* Memory cannot be physically addressed (e.g. invalid bus address) */
NMS_ERR_NULL_POINTER
NMS_ERR_NULL_POINTER,
NMS_ERR_INVALID_MODULE,
NMS_ERR_INVALID_POINTER,
NMS_LSS_NODE_CONFIG_ERROR,
} NMSErrorEn;
#endif /* NMS_TYPES_H_INCLUDED */