NMT.cpp
Go to the documentation of this file.
1 // this is for emacs file handling -*- mode: c++; indent-tabs-mode: nil -*-
2 
3 // -- BEGIN LICENSE BLOCK ----------------------------------------------
4 // This file is part of the SCHUNK Canopen Driver suite.
5 //
6 // This program is free software licensed under the LGPL
7 // (GNU LESSER GENERAL PUBLIC LICENSE Version 3).
8 // You can find a copy of this license in LICENSE folder in the top
9 // directory of the source code.
10 //
11 // © Copyright 2016 SCHUNK GmbH, Lauffen/Neckar Germany
12 // © Copyright 2016 FZI Forschungszentrum Informatik, Karlsruhe, Germany
13 // -- END LICENSE BLOCK ------------------------------------------------
14 
15 //----------------------------------------------------------------------
22 //----------------------------------------------------------------------
23 
24 #include "NMT.h"
25 #include "Logging.h"
26 
27 namespace icl_hardware {
28 namespace canopen_schunk {
29 
30 NMT::NMT(const uint8_t &node_id, const CanDevPtr &can_device):
31  m_can_device(can_device),
32  m_node_id(node_id),
33  m_state(NMTS_INITIALISATION) // All canopen devices start in this mode and send an NMT message once they switch to pre-operational
34 {
35 }
36 
37 void NMT::update(const CanMsg &msg)
38 {
39  uint8_t node_id = (msg.id - ds301::ID_NMT_ERROR_MIN)+1;
40 
41  if (node_id != m_node_id)
42  {
43  LOGGING_ERROR_C(CanOpen,NMT,"NMT Update called with wrong canopen ID. Received ID: " << node_id << " Node ID: " << m_node_id << ". Update ignored." << endl);
44  return;
45  }
46 
47  // NMT messages will ALWAYS be 1 byte long
48  // Only exception: When we are the receiving end, someone could send commands to us. However the driver is not designed for that.
49  if (msg.dlc != 1)
50  {
51  LOGGING_ERROR_C(CanOpen,NMT,"NMT Update called with illegal length message. Expected length: " << 1 << " got: " << msg.dlc << ". Update ignored." << endl);
52  return;
53  }
54 
55  uint8_t payload = msg.data[0];
56 
57  // The Bootup messages are always right
58  if (payload == 0)
59  {
60  LOGGING_INFO_C(CanOpen,NMT,"NMT Bootup complete for node " << node_id << endl);
62  }
63  else
64  {
65  // Here comes the handling of Heartbeat or nodeguard messages
66  // Regardless of protocol we want to change our current state if it is not already the right one
67  // We mask bit 1 as it is the toggle bit
68  uint8_t state_to_check = (payload & 0x7F);
69  if (isValidNmtState(state_to_check))
70  {
71  if (m_state != static_cast<eNMT_State>(state_to_check))
72  {
73  // HEARTBEAT OR NODEGUARDING FAIL!
74  LOGGING_WARNING_C(CanOpen,NMT,"NMT Nodeguarding for node " << node_id << " detected a failure! State is supposed to be: " << nmtStateToString(m_state) << " but was detected as " << nmtStateToString(static_cast<eNMT_State>(state_to_check)) << ". State changed." << endl);
75  m_state = static_cast<eNMT_State>(state_to_check);
76  }
77  else
78  {
79  // If the states match, everything is fine!
80  LOGGING_TRACE_C(CanOpen,NMT,"NMT Nodeguarding for node " << node_id << " received. ALL IS WELL!");
81  }
82  }
83  else
84  {
85  LOGGING_DEBUG_C(CanOpen,NMT,"NMT Nodeguarding for node " << node_id << " received illegal NMT state information. Ignoring message" << endl);
86  }
87  }
88 
89 }
90 
91 void NMT::start()
92 {
94 }
95 
96 void NMT::stop()
97 {
99 }
100 
102 {
104 }
105 
107 {
109 }
110 
112 {
114 }
115 
117 {
118  // The transition 2 (initialization to Pre-Operational) is an automatic one and can not be forced
119  // proactively set the internal state to the desired one.
120  switch (cmd)
121  {
122  case NMT_STARTREMOTENODE: // Transition 3,6 or none
124  break;
125  case NMT_STOPREMOTENODE:
126  m_state = NMTS_STOPPED; // Transition 5,8 or none
127  break;
129  m_state = NMTS_PRE_OPERATIONAL; //Transition 4,7 or none
130  break;
131  case NMT_RESETNODE:
132  m_state = NMTS_INITIALISATION; // Transition 9,10,11 All values will be reset to turn on default, device reboots
133  break;
135  m_state = NMTS_INITIALISATION; // Transition 12,13,14 All communication values will be reset. Device has to finish bootup sequence again.
136  break;
137  default:
138  LOGGING_ERROR_C(CanOpen,NMT,"Illegal NMT command " << cmd << " was sent to node with id " << m_node_id << " . Command ignored." << endl);
139  return; // do not send anything
140  break;
141  }
142 
143  // Send the data straight forward
144  // The NMT Commands are without response so no further actions have to be taken for the communication side.
145  unsigned char msg[2];
146  msg[0] = static_cast<unsigned char>(cmd);
147  msg[1] = m_node_id;
148  m_can_device->Send(CanMsg(ds301::ID_NMT,2,0,msg));
149 }
150 
151 }}//end of NS
void update(const CanMsg &msg)
update Updates the NMT status with newly received data
Definition: NMT.cpp:37
CanDevPtr m_can_device
can device handle for sending of NMT commands
Definition: NMT.h:202
#define LOGGING_INFO_C(streamname, classname, arg)
void resetCommunication()
resetCommunication Resets the communication of a device, setting communication values to their defaul...
Definition: NMT.cpp:111
NMT(const uint8_t &node_id, const CanDevPtr &can_device)
NMT Construct a new NMT object to manage the NMT state of a device.
Definition: NMT.cpp:30
The NMT class provides access to NMT functions of the canOpen protocol and keeps the NMT state of can...
Definition: NMT.h:42
const std::string nmtStateToString(const eNMT_State &state)
nmtStateToString Returns a string corresponding to a given NMT state
Definition: NMT.h:167
void preOperational()
preOperational switches the device back into pre-operational state where configuration can occur ...
Definition: NMT.cpp:101
bool isValidNmtState(const uint8_t &state)
isValidNmtState Helper function to check if a received value is a valid NMT state ...
Definition: NMT.h:185
#define LOGGING_WARNING_C(streamname, classname, arg)
static const uint16_t ID_NMT_ERROR_MIN
Definition: ds301.h:81
void reset()
reset Resets the device and triggers a complete reboot
Definition: NMT.cpp:106
void stop()
stop Stops the device by setting the NMT state to stopped
Definition: NMT.cpp:96
unsigned char uint8_t
#define LOGGING_DEBUG_C(streamname, classname, arg)
static const uint16_t ID_NMT
Definition: ds301.h:45
ThreadStream & endl(ThreadStream &stream)
uint8_t m_node_id
We keep the node ID which this NMT object is corresponding to.
Definition: NMT.h:205
eNMT_Command
NMT Command specifies what the state machine shall do value = "cs" as specified in ds301 7...
Definition: NMT.h:50
void sendCommand(const eNMT_Command &cmd)
sendCommand Sends an actual NMT command to the device. This will proactively change the state of the ...
Definition: NMT.cpp:116
void start()
start Starts the device by setting the NMT state to operational
Definition: NMT.cpp:91
eNMT_State
The NMT state indicates the behavior of the communication of a device, everything else is device spec...
Definition: NMT.h:60
#define LOGGING_TRACE_C(streamname, classname, arg)
icl_hardware::can::tCanMessage CanMsg
Definition: helper.h:35
#define LOGGING_ERROR_C(streamname, classname, arg)
eNMT_State m_state
Status of the NMT state machine.
Definition: NMT.h:208


schunk_canopen_driver
Author(s): Felix Mauch , Georg Heppner
autogenerated on Mon Jun 10 2019 15:07:49