Robot_Node

Dependencies:   XBeeLib_Robot mbed

Files at this revision

API Documentation at this revision

Comitter:
basvuyk
Date:
Wed Jul 25 09:13:38 2018 +0000
Commit message:
Robot_Node;

Changed in this revision

XBeeLib.lib Show annotated file Show diff for this revision Revisions of this file
config.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XBeeLib.lib	Wed Jul 25 09:13:38 2018 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/basvuyk/code/XBeeLib_Robot/#273032d9299a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config.h	Wed Jul 25 09:13:38 2018 +0000
@@ -0,0 +1,8 @@
+#include "mbed.h"
+
+#define MAX_FRAME_PAYLOAD_LEN   128
+#define FRAME_BUFFER_SIZE       4
+#define SYNC_OPS_TIMEOUT_MS     1000
+#define RADIO_TX                PA_9
+#define RADIO_RX                PA_10
+#define RADIO_RESET             PA_8
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Jul 25 09:13:38 2018 +0000
@@ -0,0 +1,284 @@
+#include "mbed.h"
+#include "XBeeLib.h"
+
+using namespace XBeeLib;
+/* System states */    
+typedef enum
+{
+    BOOTING,    
+    NORMAL_OPERATION,
+    EMERGENCY,
+    WAIT_FOR_RESET,
+    HEARTBEAT_ERROR,
+    GRACE_PERIOD,
+} state_t;
+
+state_t currentState = BOOTING;
+
+int receivedData, currentMessageCounter, graceCounter, currentTimerValue;
+int heartbeat_msg = 49, emergency_msg = 50, reset_msg = 46;
+int systemState = 1; // 0 = Emergency, 1 = System Ok
+int systemResetUsed = 0;
+
+/* Change network values */
+//------------DIGIMESH CONFIG-------//
+#define channel 0x18
+#define networkId 0xD164
+#define powerLevel 4
+#define nodeId "robotNode"
+#define baudRate 230400
+//------------DIGIMESH CONFIG-------//
+
+//------------PIN CONFIG------------//
+DigitalOut statusLED(PB_4);
+DigitalOut powerLED(PB_5);
+DigitalOut MCU_Status(PF_1);
+DigitalOut resetOutput(PA_11);
+
+DigitalIn localEstop(PA_12);
+DigitalIn safetyRelayStatus(PB_1);
+DigitalIn bumperStatus(PB_0);
+//------------PIN CONFIG------------//
+
+//-----------SPI CONFIG------------//
+SPI spi(PA_7, PA_6, PA_5);      // mosi, miso, sclk
+DigitalOut chipSelect(PA_4);    // nss
+#define spiSpeed 10000000
+//-----------SPI CONFIG------------//
+
+//-----------TIMER CONFIG----------//
+Timer runCheckHeartbeatTimer, runSystemChecksTimer;
+#define systemCheckTimeout 5    // ms   // Check system state every 5ms
+#define heartbeatTimeout 100    // ms   // Check heartbeat every 100ms
+//-----------TIMER CONFIG----------//
+
+/* If heartbeat is missed for more then 10 times, 
+system goes into HEARTBEAT_ERROR state.
+The reset relay is activated for 100*5ms to ensure
+the emergencystop relay is reverting to normal state.
+Changing this time to lower values causes the emergencystop
+relay to not always acknowledge the reset */
+//-----------SYSTEM VARIABLES------//
+#define hearbeatMisses 10               
+#define resetRelayActivationTime 100
+//-----------SYSTEM VARIABLES------//
+
+/* Config XBee radio. All the previously defined 
+values are written to the XBee module. DMLocalNode.write_config()
+is used to save the values to the rom of the module. */
+// RADIO CONFIG
+void radioConfig(XBeeDM &DMLocalNode){    
+    RadioStatus temp = DMLocalNode.init();
+    temp = DMLocalNode.set_channel(channel);
+    temp = DMLocalNode.set_network_id(networkId);
+    temp = DMLocalNode.set_power_level(powerLevel);
+    temp = DMLocalNode.set_node_identifier(nodeId);
+    temp = DMLocalNode.write_config();
+}
+
+/* Functions who need to run once are performed here */
+void boot(XBeeDM &DMLocalNode){
+    radioConfig(DMLocalNode);
+    statusLED.write(1);
+    powerLED.write(1);
+        
+    spi.format(8,3);
+    spi.frequency(spiSpeed);
+}
+
+/* If a message has been received, this function
+is used to retreive the message from the buffer.
+A substraction of 3 is used to get the right value. 
+This is due to some conversion being done in the library */
+static void receive_cb(const RemoteXBeeDM& remote, bool broadcast, const uint8_t *const data, uint16_t len){
+    receivedData = (data[0]-3);
+}
+
+/* If a message is to be sent, this function
+is used to send the message. */
+static void sendMessage(XBeeDM &DMLocalNode, char *sendData){
+    const char data[] = {*sendData};
+    const uint16_t data_len = strlen(data);
+
+    const TxStatus txStatus = DMLocalNode.send_data_broadcast((const uint8_t *)data, data_len);
+    
+    powerLED = !powerLED;
+}
+
+/* This function checks the physical E-Stop status. */
+void checkSystemStatus(){
+    if (localEstop == 0 || bumperStatus == 0 ){
+        currentState = EMERGENCY;
+        systemState = 0;
+    }
+    if (localEstop == 1 && bumperStatus == 1 && currentState == EMERGENCY){
+        currentState = WAIT_FOR_RESET;
+        systemState = 1; 
+    }
+}
+
+/* This function checks if a system state change is
+needed, and performs the necessary actions tied to 
+this state */
+void stateHandler(XBeeDM &DMLocalNode){        
+    if (currentState == NORMAL_OPERATION){
+        checkSystemStatus();
+        MCU_Status.write(1);
+        statusLED.write(0);        
+        powerLED.write(1);
+                
+        if (systemResetUsed != resetRelayActivationTime){
+            resetOutput.write(1);
+            systemResetUsed++; 
+        }
+        if (systemResetUsed == resetRelayActivationTime){
+            resetOutput.write(0);
+        }
+    }
+    
+    if (currentState == EMERGENCY && currentMessageCounter != 5){
+        sendMessage(DMLocalNode, "50");
+        checkSystemStatus();
+        currentMessageCounter++;
+        
+        MCU_Status.write(0);
+        statusLED.write(1);
+        powerLED.write(0);
+        
+        systemResetUsed = 0; 
+    }
+    
+    if (currentState == WAIT_FOR_RESET){
+        currentMessageCounter = 0;
+        
+        MCU_Status.write(0);
+        statusLED.write(1);
+        powerLED.write(0);
+        
+        systemResetUsed = 0;
+    }
+    
+    if (currentState == HEARTBEAT_ERROR){
+        MCU_Status.write(0);
+        statusLED.write(0);
+        powerLED.write(0);
+        
+        systemResetUsed = 0; 
+    }
+    
+    if (currentState == GRACE_PERIOD){
+        graceCounter++;
+        if (graceCounter == 40){
+            currentState = NORMAL_OPERATION;
+            graceCounter = 0;
+        }
+    }
+}
+
+/* If a heartbeat message has been received
+currentHeartbeatValue is reset */
+void heartbeatTimerReset(){
+    currentTimerValue = 0;
+}
+
+/* If more heartbeats are missed then allowed
+the system enters the HEARTBEAT_ERROR state */
+void checkHeartbeat(){
+    if (currentState == NORMAL_OPERATION){
+    currentTimerValue++;
+        if (currentTimerValue > hearbeatMisses){
+            currentState = HEARTBEAT_ERROR;
+        }
+    }   
+}
+
+
+/* Incoming message are handled here and necessary
+actions are taken if needed */
+void handleMessages(XBeeDM &DMLocalNode){
+    if (receivedData == emergency_msg){
+        currentState = EMERGENCY;
+        graceCounter = 0;
+    }
+    
+/* The system enters the GRACE_PERIOD state if
+the previous state was WAITING_FOR_RESET and a
+reset message has been received. If a emergency
+message is received in this period, the system, 
+again, enters the WAIT_FOR_RESET state. This means
+that there are one or multiple nodes still in 
+EMERGENCY_STATE. Check all nodes to ensure all of
+them have been taken care of*/ 
+    if (currentState == WAIT_FOR_RESET && systemState == 1 && receivedData == reset_msg){
+        currentState = GRACE_PERIOD;
+    }
+    
+    if (receivedData == heartbeat_msg){
+        heartbeatTimerReset();
+    }
+    
+    if (receivedData == heartbeat_msg && currentState == HEARTBEAT_ERROR){
+        currentState = WAIT_FOR_RESET;
+        heartbeatTimerReset();
+    }
+    
+    if (currentState == EMERGENCY && currentMessageCounter == 5 && receivedData == reset_msg){
+        currentMessageCounter = 0;
+    }
+}
+
+// Handle SPI messages
+void handleSPI(){
+    chipSelect = 0; // Select device
+    spi.write(systemState);
+    chipSelect = 1; // Deselect device
+}
+
+void runSystemChecks(XBeeDM &DMLocalNode){
+    stateHandler(DMLocalNode);
+    handleMessages(DMLocalNode);
+    handleSPI();
+}
+
+int main() {
+/* The creation of the DMLocalNode */
+    XBeeDM DMLocalNode = XBeeDM(RADIO_TX, RADIO_RX, RADIO_RESET, NC, NC, baudRate);
+ 
+ /* Perform boot functions and create the callback
+for the received messages */   
+    boot(DMLocalNode);
+    DMLocalNode.register_receive_cb(&receive_cb);
+    
+/* Upon boot the system waits to be included in 
+the network. A reset can be given at any point, 
+this does not interfere with the current state
+of the network. Thus a new node can be included 
+whenever */
+    currentState = WAIT_FOR_RESET;
+    
+/* Start timers */    
+    runSystemChecksTimer.start();
+    runCheckHeartbeatTimer.start();
+    
+    static int systemTaskCounter, checkHeartbeatCounter;
+    
+   while(1){
+        systemTaskCounter = runSystemChecksTimer.read_ms();
+        checkHeartbeatCounter = runCheckHeartbeatTimer.read_ms();
+        
+        checkSystemStatus();
+        if ( systemTaskCounter > systemCheckTimeout){
+            DMLocalNode.process_rx_frames();
+            runSystemChecks(DMLocalNode);
+            systemTaskCounter = 0;
+            runSystemChecksTimer.reset();
+            receivedData = 0; 
+        }    
+        
+        if (checkHeartbeatCounter > heartbeatTimeout){
+            checkHeartbeat();   
+            runCheckHeartbeatTimer.reset();
+            checkHeartbeatCounter = 0;
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Jul 25 09:13:38 2018 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/994bdf8177cb
\ No newline at end of file