This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

LP-AM243: Need help on Ethernet/ip EDS file and Codesys

Part Number: LP-AM243

Tool/software:

I have problems with EDS file and Codesys. Please check if my program is ok for Ethernet/ip.

Thanks,

Thien Tran

// *****************************************************************************
// File: app8AI.c
// Description: 8 analog inputs (internal ADC), each selectable as 0–5V or 4–20mA
// Compatible with EtherNet/IP attribute access via CIP class 0x70, instance 0x01.
// *****************************************************************************

#include "app8AI.h"
#include <kernel/dpl/ClockP.h>
#include <kernel/dpl/DebugP.h>
#include <drivers/adc.h>
#include "ti_drivers_config.h"
#include "ti_drivers_open_close.h"
#include "EI_API.h"

// Internal buffer for raw ADC results
static uint16_t gEI_APP_8AI_results[EI_APP_8AI_NUM_CHANNELS] = {0};

// Per-channel mode: 0 = Voltage (0–5V), 1 = Current (4–20mA)
static uint8_t gEI_APP_8AI_mode[EI_APP_8AI_NUM_CHANNELS] = {0};

void EI_APP_8AI_setChannelMode(uint8_t index, uint8_t mode)
{
if (index < EI_APP_8AI_NUM_CHANNELS)
{
gEI_APP_8AI_mode[index] = (mode != 0) ? 1 : 0;
}
}

void EI_APP_8AI_init(void)
{
uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR;
adcStepConfig_t adcConfig;
uint32_t chCnt, adcStep;
int32_t configStatus;

ADCPowerUp(baseAddr, TRUE);
ClockP_usleep(5U);
ADCInit(baseAddr, FALSE, 0U, 0U);

adcConfig.mode = ADC_OPERATION_MODE_SINGLE_SHOT;
adcConfig.openDelay = 0x1U;
adcConfig.sampleDelay = 0U;
adcConfig.rangeCheckEnable = 0U;
adcConfig.averaging = ADC_AVERAGING_16_SAMPLES;
adcConfig.fifoNum = ADC_FIFO_NUM_0;

for (chCnt = 0U; chCnt < EI_APP_8AI_NUM_CHANNELS; chCnt++)
{
adcConfig.channel = ADC_CHANNEL_1 + chCnt;
adcStep = ADC_STEP_1 + chCnt;
configStatus = ADCSetStepParams(baseAddr, adcStep, &adcConfig);
DebugP_assert(SystemP_SUCCESS == configStatus);
ADCStepEnable(baseAddr, adcStep, TRUE);
}

ADCStepIdTagEnable(baseAddr, TRUE);
configStatus = ADCSetCPUFIFOThresholdLevel(baseAddr, ADC_FIFO_NUM_0, 40U);
DebugP_assert(SystemP_SUCCESS == configStatus);
}

void EI_APP_8AI_readInputs(void)
{
uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR;
uint32_t fifoData, fifoWordCnt, stepID;

ADCStart(baseAddr, TRUE);
ClockP_usleep(200);

fifoWordCnt = ADCGetFIFOWordCount(baseAddr, ADC_FIFO_NUM_0);
for (uint32_t i = 0U; i < fifoWordCnt; i++)
{
fifoData = ADCGetFIFOData(baseAddr, ADC_FIFO_NUM_0);
stepID = (fifoData & ADC_FIFODATA_ADCCHNLID_MASK) >> ADC_FIFODATA_ADCCHNLID_SHIFT;
fifoData = (fifoData & ADC_FIFODATA_ADCDATA_MASK) >> ADC_FIFODATA_ADCDATA_SHIFT;

if (stepID < EI_APP_8AI_NUM_CHANNELS)
{
gEI_APP_8AI_results[stepID] = fifoData;
}
}

ADCStart(baseAddr, FALSE);
}

uint16_t EI_APP_8AI_convertTo_mV(uint16_t raw)
{
return (raw * EI_APP_8AI_REF_VOLTAGE_MV) / 4095U;
}

uint16_t EI_APP_8AI_convertTo_uA(uint16_t raw)
{
uint16_t mV = EI_APP_8AI_convertTo_mV(raw);
return (mV * 1000U) / 250U; // 250 ohm shunt resistor
}

uint16_t EI_APP_8AI_getValue(uint8_t channelIndex)
{
if (channelIndex < EI_APP_8AI_NUM_CHANNELS)
return gEI_APP_8AI_results[channelIndex];
return 0;
}

uint16_t EI_APP_8AI_getEngineeringUnits(uint8_t channelIndex)
{
if (channelIndex >= EI_APP_8AI_NUM_CHANNELS)
return 0;

uint16_t raw = gEI_APP_8AI_results[channelIndex];

if (gEI_APP_8AI_mode[channelIndex] == 0)
return EI_APP_8AI_convertTo_mV(raw); // Return in mV
else
return EI_APP_8AI_convertTo_uA(raw); // Return in uA
}

void EI_APP_8AI_deInit(void)
{
uint32_t baseAddr = CONFIG_ADC0_BASE_ADDR;

for (uint32_t chCnt = 0U; chCnt < EI_APP_8AI_NUM_CHANNELS; chCnt++)
{
ADCStepEnable(baseAddr, ADC_STEP_1 + chCnt, FALSE);
}

ADCStart(baseAddr, FALSE);
ADCPowerUp(baseAddr, FALSE);
}

// -----------------------------------------------------------------------------
// EtherNet/IP Attribute Update Function
// -----------------------------------------------------------------------------
void EI_APP_8AI_updateCIPAttributes(EI_API_CIP_NODE_T *pCipNode)
{
EI_APP_8AI_readInputs();

for (uint16_t i = 0; i < EI_APP_8AI_NUM_CHANNELS; i++)
{
uint16_t eng = EI_APP_8AI_getEngineeringUnits(i);
uint8_t scaled = eng >> 4; // Scale to fit 0–255 range (USINT)

// Use attribute ID range 0x0310–0x0317
EI_API_CIP_setAttr_usint(pCipNode, 0x70, 0x01, 0x0310 + i, scaled);
}
}

  • Hi Thien,

    the code related to EtherNet/IP can be correct, you are updating some attributes with your ADC values. I assume you want to send those values via IO connection, then If your producing assembly is also configured to use those attributes then you would see them also reflected in IO data exchange.

    The function "EI_APP_8AI_updateCIPAttributes" should of course be called periodically to update the attributes.

    Best regards,
    Pourya