Skip to content

Commit 3ee5179

Browse files
committed
Implement reading of PWM pulse width from Arduino_Opta_Blueprint.
1 parent 0f8ef0f commit 3ee5179

File tree

7 files changed

+142
-40
lines changed

7 files changed

+142
-40
lines changed

examples/opcua_server/opcua_server.ino

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,13 +354,17 @@ void setup()
354354
exp_analog->add_pwm_output(
355355
opc_ua_server,
356356
pwm_out_name,
357-
[i, p](uint32_t const pwm_period_ms, uint32_t const pwm_pulse_width_ms)
357+
[i, p](uint32_t const pwm_period_us, uint32_t const pwm_pulse_width_us)
358358
{
359-
reinterpret_cast<AnalogExpansion *>(OptaController.getExpansionPtr(i))->setPwm(p, pwm_period_ms, pwm_pulse_width_ms);
359+
reinterpret_cast<AnalogExpansion *>(OptaController.getExpansionPtr(i))->setPwm(p, pwm_period_us, pwm_pulse_width_us);
360360
},
361361
[i, p](void) -> uint32_t
362362
{
363363
return reinterpret_cast<AnalogExpansion *>(OptaController.getExpansionPtr(i))->getPwmPeriod(p - OA_PWM_CH_FIRST);
364+
},
365+
[i, p](void) -> uint32_t
366+
{
367+
return reinterpret_cast<AnalogExpansion *>(OptaController.getExpansionPtr(i))->getPwmPulse(p - OA_PWM_CH_FIRST);
364368
});
365369
pwm_output_num++;
366370
}

src/expansion/AnalogExpansion.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,10 @@ AnalogExpansion::add_pwm_output(
9292
UA_Server * server,
9393
const char * display_name,
9494
PwmOutput::SetPwmFunc const set_pwm_func,
95-
PwmOutput::GetPwmPeriodFunc const get_pwm_period_func)
95+
PwmOutput::GetPwmPeriodFunc const get_pwm_period_func,
96+
PwmOutput::GetPwmPulseWidthFunc const get_pwm_pulse_width_func)
9697
{
97-
_pwm_output_mgr->add_pwm_output(server, display_name, set_pwm_func, get_pwm_period_func);
98+
_pwm_output_mgr->add_pwm_output(server, display_name, set_pwm_func, get_pwm_period_func, get_pwm_pulse_width_func);
9899
}
99100

100101
void

src/expansion/AnalogExpansion.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ class AnalogExpansion : public Expansion
7272
UA_Server * server,
7373
const char * display_name,
7474
PwmOutput::SetPwmFunc const set_pwm_func,
75-
PwmOutput::GetPwmPeriodFunc const get_pwm_period_func);
75+
PwmOutput::GetPwmPeriodFunc const get_pwm_period_func,
76+
PwmOutput::GetPwmPulseWidthFunc const get_pwm_pulse_width_func);
7677

7778
void
7879
add_led_output(

src/io/pwm/PwmOutput.cpp

Lines changed: 110 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,22 @@ pwm_output_on_write_request_pwm_period(
4949
const UA_DataValue *data)
5050
{
5151
PwmOutput * this_ptr = reinterpret_cast<PwmOutput *>(nodeContext);
52-
uint32_t const pwm_period_ms = *(UA_UInt32 *)(data->value.data);
53-
this_ptr->onWriteRequestPwmPeriod(server, nodeid, pwm_period_ms);
52+
uint32_t const pwm_period_us = *(UA_UInt32 *)(data->value.data);
53+
this_ptr->onWriteRequestPwmPeriod(server, nodeid, pwm_period_us);
54+
}
55+
56+
static void
57+
pwm_output_on_read_request_pwm_pulse_width(
58+
UA_Server *server,
59+
const UA_NodeId *sessionId,
60+
void *sessionContext,
61+
const UA_NodeId *nodeid,
62+
void *nodeContext,
63+
const UA_NumericRange *range,
64+
const UA_DataValue *data)
65+
{
66+
PwmOutput * this_ptr = reinterpret_cast<PwmOutput *>(nodeContext);
67+
this_ptr->onReadRequestPwmPulseWidth(server, nodeid);
5468
}
5569

5670
static void
@@ -64,8 +78,8 @@ pwm_output_on_write_request_pwm_pulse_width(
6478
const UA_DataValue *data)
6579
{
6680
PwmOutput * this_ptr = reinterpret_cast<PwmOutput *>(nodeContext);
67-
uint32_t const pwm_pulse_width_ms = *(UA_UInt32 *)(data->value.data);
68-
this_ptr->onWriteRequestPwmPulseWidth(server, nodeid, pwm_pulse_width_ms);
81+
uint32_t const pwm_pulse_width_us = *(UA_UInt32 *)(data->value.data);
82+
this_ptr->onWriteRequestPwmPulseWidth(server, nodeid, pwm_pulse_width_us);
6983
}
7084

7185
/**************************************************************************************
@@ -74,13 +88,17 @@ pwm_output_on_write_request_pwm_pulse_width(
7488

7589
PwmOutput::PwmOutput(
7690
UA_NodeId const & pwm_period_node_id,
91+
UA_NodeId const & pwm_pulse_width_node_id,
7792
SetPwmFunc const set_pwm_func,
78-
GetPwmPeriodFunc const get_pwm_period_func)
93+
GetPwmPeriodFunc const get_pwm_period_func,
94+
GetPwmPulseWidthFunc const get_pwm_pulse_width_func)
7995
: _pwm_period_node_id{pwm_period_node_id}
96+
, _pwm_pulse_width_node_id{pwm_pulse_width_node_id}
8097
, _set_pwm_func{set_pwm_func}
8198
, _get_pwm_period_func{get_pwm_period_func}
82-
, _pwm_period_ms{0}
83-
, _pwm_pulse_width_ms{0}
99+
, _get_pwm_pulse_width_func{get_pwm_pulse_width_func}
100+
, _pwm_period_us{0}
101+
, _pwm_pulse_width_us{0}
84102
{
85103

86104
}
@@ -95,7 +113,8 @@ PwmOutput::create(
95113
UA_NodeId const & parent_node_id,
96114
const char * display_name,
97115
SetPwmFunc const set_pwm_func,
98-
GetPwmPeriodFunc const get_pwm_period_func)
116+
GetPwmPeriodFunc const get_pwm_period_func,
117+
GetPwmPulseWidthFunc const get_pwm_pulse_width_func)
99118
{
100119
UA_StatusCode rc = UA_STATUSCODE_GOOD;
101120

@@ -123,7 +142,7 @@ PwmOutput::create(
123142
UA_Boolean pwm_output_period_value = get_pwm_period_func();
124143
UA_Variant_setScalar(&pwm_out_period_value_attr.value, &pwm_output_period_value, &UA_TYPES[UA_TYPES_UINT32]);
125144

126-
pwm_out_period_value_attr.displayName = UA_LOCALIZEDTEXT("en-US", "PWM Period / ms");
145+
pwm_out_period_value_attr.displayName = UA_LOCALIZEDTEXT("en-US", "PWM Period / us");
127146
pwm_out_period_value_attr.dataType = UA_TYPES[UA_TYPES_UINT32].typeId;
128147
pwm_out_period_value_attr.accessLevel =
129148
UA_ACCESSLEVELMASK_READ |
@@ -135,7 +154,7 @@ PwmOutput::create(
135154
UA_NODEID_NULL,
136155
pwm_obj_node_id,
137156
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
138-
UA_QUALIFIEDNAME(1, "PWM Period / ms"),
157+
UA_QUALIFIEDNAME(1, "pwm_period_us"),
139158
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
140159
pwm_out_period_value_attr,
141160
NULL,
@@ -147,25 +166,72 @@ PwmOutput::create(
147166
return nullptr;
148167
}
149168

150-
/* Create an instance of AnalogOutput here. */
151-
auto const instance_ptr = std::make_shared<PwmOutput>(pwm_period_node_id, set_pwm_func, get_pwm_period_func);
169+
UA_ValueCallback pwm_period_callback;
170+
pwm_period_callback.onRead = pwm_output_on_read_request_pwm_period;
171+
pwm_period_callback.onWrite = pwm_output_on_write_request_pwm_period;
172+
rc = UA_Server_setVariableNode_valueCallback(server, pwm_period_node_id, pwm_period_callback);
173+
if (UA_StatusCode_isBad(rc))
174+
{
175+
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
176+
"%s: UA_Server_setVariableNode_valueCallback(pwm_period_node_id, ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc));
177+
return nullptr;
178+
}
179+
180+
UA_VariableAttributes pwm_out_pulse_width_value_attr = UA_VariableAttributes_default;
181+
182+
UA_Boolean pwm_output_pulse_width_value = get_pwm_pulse_width_func();
183+
UA_Variant_setScalar(&pwm_out_pulse_width_value_attr.value, &pwm_output_pulse_width_value, &UA_TYPES[UA_TYPES_UINT32]);
184+
185+
pwm_out_pulse_width_value_attr.displayName = UA_LOCALIZEDTEXT("en-US", "PWM Pulse Width / us");
186+
pwm_out_pulse_width_value_attr.dataType = UA_TYPES[UA_TYPES_UINT32].typeId;
187+
pwm_out_pulse_width_value_attr.accessLevel =
188+
UA_ACCESSLEVELMASK_READ |
189+
UA_ACCESSLEVELMASK_WRITE | UA_ACCESSLEVELMASK_STATUSWRITE |
190+
UA_ACCESSLEVELMASK_TIMESTAMPWRITE; /* Status and timestamp write access necessary for opcua-client. */
191+
192+
UA_NodeId pwm_pulse_width_node_id;
193+
rc = UA_Server_addVariableNode(server,
194+
UA_NODEID_NULL,
195+
pwm_obj_node_id,
196+
UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT),
197+
UA_QUALIFIEDNAME(1, "pwm_pulse_width_us"),
198+
UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE),
199+
pwm_out_pulse_width_value_attr,
200+
NULL,
201+
&pwm_pulse_width_node_id);
202+
if (UA_StatusCode_isBad(rc))
203+
{
204+
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
205+
"%s: failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc));
206+
return nullptr;
207+
}
208+
209+
UA_ValueCallback pwm_pulse_width_callback;
210+
pwm_pulse_width_callback.onRead = pwm_output_on_read_request_pwm_pulse_width;
211+
pwm_pulse_width_callback.onWrite = pwm_output_on_write_request_pwm_pulse_width;
212+
rc = UA_Server_setVariableNode_valueCallback(server, pwm_pulse_width_node_id, pwm_pulse_width_callback);
213+
if (UA_StatusCode_isBad(rc))
214+
{
215+
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
216+
"%s: UA_Server_setVariableNode_valueCallback(pwm_pulse_width_node_id, ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc));
217+
return nullptr;
218+
}
219+
220+
auto const instance_ptr = std::make_shared<PwmOutput>(pwm_period_node_id, pwm_pulse_width_node_id, set_pwm_func, get_pwm_period_func, get_pwm_pulse_width_func);
152221

153222
rc = UA_Server_setNodeContext(server, pwm_period_node_id, reinterpret_cast<void *>(instance_ptr.get()));
154223
if (UA_StatusCode_isBad(rc))
155224
{
156225
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
157-
"%s: UA_Server_setNodeContext(...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc));
226+
"%s: UA_Server_setNodeContext(pwm_period_node_id, ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc));
158227
return nullptr;
159228
}
160229

161-
UA_ValueCallback pwm_period_callback;
162-
pwm_period_callback.onRead = pwm_output_on_read_request_pwm_period;
163-
pwm_period_callback.onWrite = pwm_output_on_write_request_pwm_period;
164-
rc = UA_Server_setVariableNode_valueCallback(server, pwm_period_node_id, pwm_period_callback);
230+
rc = UA_Server_setNodeContext(server, pwm_pulse_width_node_id, reinterpret_cast<void *>(instance_ptr.get()));
165231
if (UA_StatusCode_isBad(rc))
166232
{
167233
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,
168-
"%s: UA_Server_setVariableNode_valueCallback(pwm_period_node_id, ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc));
234+
"%s: UA_Server_setNodeContext(pwm_pulse_width_node_id, ...) failed with %s", __PRETTY_FUNCTION__, UA_StatusCode_name(rc));
169235
return nullptr;
170236
}
171237

@@ -186,29 +252,46 @@ PwmOutput::onReadRequestPwmPeriod(
186252
UA_Variant_setScalar(&in_x_val_opcua_variant, &in_x_val_opcua_value, &UA_TYPES[UA_TYPES_UINT32]);
187253
UA_Server_writeValue(server, *node_id, in_x_val_opcua_variant);
188254
/* Some debug output. */
189-
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d ms", __PRETTY_FUNCTION__, in_x_val);
255+
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d us", __PRETTY_FUNCTION__, in_x_val);
190256
}
191257

192258
void
193259
PwmOutput::onWriteRequestPwmPeriod(
194260
UA_Server * server,
195261
UA_NodeId const * pwm_period_node_id,
196-
uint32_t const pwm_period_ms)
262+
uint32_t const pwm_period_us)
263+
{
264+
_pwm_period_us = pwm_period_us;
265+
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d us, pulse width = %d us", __PRETTY_FUNCTION__, _pwm_period_us, _pwm_pulse_width_us);
266+
_set_pwm_func(_pwm_period_us, _pwm_pulse_width_us);
267+
}
268+
269+
void
270+
PwmOutput::onReadRequestPwmPulseWidth(
271+
UA_Server * server,
272+
UA_NodeId const * node_id)
197273
{
198-
_pwm_period_ms = pwm_period_ms;
199-
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d ms, pulse width = %d ms", __PRETTY_FUNCTION__, _pwm_period_ms, _pwm_pulse_width_ms);
200-
_set_pwm_func(_pwm_period_ms, _pwm_pulse_width_ms);
274+
/* Obtain the value of the analog input pin. */
275+
uint32_t const in_x_val = _get_pwm_pulse_width_func();
276+
/* Update the variable node. */
277+
UA_UInt32 in_x_val_opcua_value = in_x_val;
278+
UA_Variant in_x_val_opcua_variant;
279+
UA_Variant_init(&in_x_val_opcua_variant);
280+
UA_Variant_setScalar(&in_x_val_opcua_variant, &in_x_val_opcua_value, &UA_TYPES[UA_TYPES_UINT32]);
281+
UA_Server_writeValue(server, *node_id, in_x_val_opcua_variant);
282+
/* Some debug output. */
283+
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm pulse width = %d us", __PRETTY_FUNCTION__, in_x_val);
201284
}
202285

203286
void
204287
PwmOutput::onWriteRequestPwmPulseWidth(
205288
UA_Server * server,
206289
UA_NodeId const * node_id,
207-
uint32_t const pwm_pulse_width_ms)
290+
uint32_t const pwm_pulse_width_us)
208291
{
209-
_pwm_pulse_width_ms = pwm_pulse_width_ms;
210-
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d ms, pulse width = %d ms", __PRETTY_FUNCTION__, _pwm_period_ms, _pwm_pulse_width_ms);
211-
_set_pwm_func(_pwm_period_ms, _pwm_pulse_width_ms);
292+
_pwm_pulse_width_us = pwm_pulse_width_us;
293+
UA_LOG_INFO(UA_Log_Stdout, UA_LOGCATEGORY_SERVER, "%s: pwm period = %d us, pulse width = %d us", __PRETTY_FUNCTION__, _pwm_period_us, _pwm_pulse_width_us);
294+
_set_pwm_func(_pwm_period_us, _pwm_pulse_width_us);
212295
}
213296

214297
/**************************************************************************************

src/io/pwm/PwmOutput.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class PwmOutput
3737
typedef std::shared_ptr<PwmOutput> SharedPtr;
3838
typedef std::function<void(uint32_t const, uint32_t const)> SetPwmFunc;
3939
typedef std::function<uint32_t(void)> GetPwmPeriodFunc;
40+
typedef std::function<uint32_t(void)> GetPwmPulseWidthFunc;
4041

4142

4243
static SharedPtr
@@ -45,13 +46,16 @@ class PwmOutput
4546
UA_NodeId const & parent_node_id,
4647
const char * display_name,
4748
SetPwmFunc const set_pwm_func,
48-
GetPwmPeriodFunc const get_pwm_period_func);
49+
GetPwmPeriodFunc const get_pwm_period_func,
50+
GetPwmPulseWidthFunc const get_pwm_pulse_width_func);
4951

5052

5153
PwmOutput(
5254
UA_NodeId const & pwm_period_node_id,
55+
UA_NodeId const & pwm_pulse_width_node_id,
5356
SetPwmFunc const set_pwm_func,
54-
GetPwmPeriodFunc const get_pwm_period_func);
57+
GetPwmPeriodFunc const get_pwm_period_func,
58+
GetPwmPulseWidthFunc const get_pwm_pulse_width_func);
5559

5660

5761
void
@@ -63,20 +67,27 @@ class PwmOutput
6367
onWriteRequestPwmPeriod(
6468
UA_Server * server,
6569
UA_NodeId const * pwm_period_node_id,
66-
uint32_t const pwm_period_ms);
70+
uint32_t const pwm_period_us);
71+
72+
void
73+
onReadRequestPwmPulseWidth(
74+
UA_Server * server,
75+
UA_NodeId const * node_id);
6776

6877
void
6978
onWriteRequestPwmPulseWidth(
7079
UA_Server * server,
7180
UA_NodeId const * node_id,
72-
uint32_t const pwm_pulse_width_ms);
81+
uint32_t const pwm_pulse_width_us);
7382

7483

7584
private:
7685
UA_NodeId _pwm_period_node_id;
86+
UA_NodeId _pwm_pulse_width_node_id;
7787
SetPwmFunc const _set_pwm_func;
7888
GetPwmPeriodFunc const _get_pwm_period_func;
79-
uint32_t _pwm_period_ms, _pwm_pulse_width_ms;
89+
GetPwmPulseWidthFunc const _get_pwm_pulse_width_func;
90+
uint32_t _pwm_period_us, _pwm_pulse_width_us;
8091
};
8192

8293
/**************************************************************************************

src/io/pwm/PwmOutputManager.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,10 @@ PwmOutputManager::add_pwm_output(
7474
UA_Server * server,
7575
const char * display_name,
7676
PwmOutput::SetPwmFunc const set_pwm_func,
77-
PwmOutput::GetPwmPeriodFunc const get_pwm_period_func)
77+
PwmOutput::GetPwmPeriodFunc const get_pwm_period_func,
78+
PwmOutput::GetPwmPulseWidthFunc const get_pwm_pulse_width_func)
7879
{
79-
auto const pwm_output = PwmOutput::create(server, _node_id, display_name, set_pwm_func, get_pwm_period_func);
80+
auto const pwm_output = PwmOutput::create(server, _node_id, display_name, set_pwm_func, get_pwm_period_func, get_pwm_pulse_width_func);
8081
if (!pwm_output)
8182
{
8283
UA_LOG_ERROR(UA_Log_Stdout, UA_LOGCATEGORY_SERVER,

src/io/pwm/PwmOutputManager.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ class PwmOutputManager
5151
UA_Server * server,
5252
const char * display_name,
5353
PwmOutput::SetPwmFunc const set_pwm_func,
54-
PwmOutput::GetPwmPeriodFunc const get_pwm_period_func);
54+
PwmOutput::GetPwmPeriodFunc const get_pwm_period_func,
55+
PwmOutput::GetPwmPulseWidthFunc const get_pwm_pulse_width_func);
5556

5657

5758
private:

0 commit comments

Comments
 (0)