This is example code that can get you started with building your own IR vision robot that communicates over LoRa

Dependencies:   Adafruit-MotorShield Adafruit-PWM-Servo-Driver Adafruit_GFX BufferedSerial MAX17055_EZconfig NEO-6m-GPS SX1276GenericLib USBDeviceHT max32630fthr max77650_charger_sample

Fork of MAX326xxFTHR_LoRa_Example_test by Devin Alexander

Revision:
42:911770814147
Parent:
41:1381a49e019e
--- a/main.cpp	Wed Aug 01 08:32:21 2018 +0000
+++ b/main.cpp	Wed Aug 15 04:06:09 2018 +0000
@@ -1,10 +1,4 @@
 /*
- * Copyright (c) 2018 HELIOS Software GmbH
- * 30826 Garbsen (Hannover) Germany
- * Licensed under the Apache License, Version 2.0);
- */
-  
- /*
  * For Wiring Instructions, please visit the link below:
  * https://www.hackster.io/DevinAlex64/getting-started-with-the-max32620fthr-and-lora-f9d8dd\
  */
@@ -18,6 +12,9 @@
 //#define DEBUG_GRID_EYE
 //#define DEBUG_MAX17055
 #define RASPBERRY_PI
+#define NUM_TIMEOUTS_TO_STOP_ROBOT 15
+#define OLED_FREQ 1000
+
 DigitalOut myled(LED);
 Serial pc(USBTX, USBRX);
 
@@ -102,43 +99,6 @@
     
     void charger_Detect();
     bool chrg_State_fn();
-    
-    void charger_Detect() 
-    {
-    
-        uint8_t int_chr_value,temp, int_chr_MASK = 0x04;         
-        int status; 
-        pc.printf("Charger Detected \n");
-        status = simo_pmic.readReg(MAX77650::INT_CHG, int_chr_value);
-            pc.printf("INT_CHR val= %X  \n", int_chr_value);
-            if (status == 1){
-                temp = int_chr_value & int_chr_MASK;
-                pc.printf("INT_CHR anded= %X  \n", temp);
-                if (temp == 4){
-                    pc.printf("enable charger \n");
-                    simo_pmic.enCharger();
-                }
-            }
-    }
-    
-    bool chrg_State_fn()
-    {
-        uint8_t status_chr_value,temp, chr_status_MASK = 0x02;         
-        int status; 
-        pc.printf("Charger State \n");
-        status = simo_pmic.readReg(MAX77650::STAT_CHG_B, status_chr_value);
-            pc.printf("STAR_CHG_B val= %X  \n", status_chr_value);
-            if (status == 1){
-                temp = status_chr_value & chr_status_MASK;
-                pc.printf("STAR_CHG_B val= %X  \n", temp);
-                if (temp == 2){
-                    return true; 
-                }
-                return false; 
-            }
-            return false;
-    }
-    
 #endif
 
  
@@ -239,7 +199,7 @@
  * Motor Controller Instatiation and Related Functions
  **************************************************************************/
 #if   defined(TARGET_MAX32630FTHR) // Master Device: MAX32630FTHR BLE-to-LoRa Gateway
-    // There is no motor on this device.
+    // There is no motor controller on this device.
 #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
     /* This is a port of a library that was developed by Adafruit for the Arduino. 
      * This port was done by mbed user syundo0730. */
@@ -255,7 +215,7 @@
     // Create the motor shield object with the default I2C address
     Adafruit_MotorShield AFMS = Adafruit_MotorShield(P3_4, P3_5, 0x60 << 1); // You have to shift it over by one due to how mbed does its I2C Addressing. 
     // Or, create it with a different I2C address (say for stacking)
-    // Adafruit_MotorShield AFMS = Adafruit_MotorShield(0x61); 
+    // Adafruit_MotorShield AFMS = Adafruit_MotorShield(P3_4, P3_5, 0x61 << 1); 
     // Select which 'port' M1, M2, M3 or M4. In this case, M1
     Adafruit_DCMotor *rightMotor = AFMS.getMotor(1);
     // You can also make another motor on port M4
@@ -350,8 +310,6 @@
   
     dprintf("Starting a simple LoRa PingPong");
     
-
-    
     
     /***************************************************************************
      * Grid Eye Sensor: Non-Buffer Program Variables
@@ -524,7 +482,8 @@
         design_param.vcharge = 4200;  // Battery Charge Voltage can be obtained from MAX77650 configuration
         design_param.rsense = 5; //5mOhms
     
-        int oper_f1, volt_mod_FG, status;
+        int oper_f1, volt_mod_FG;
+        int status; // stores return value of the status of setting up the MAX17055
         
         //serial.printf("Test Init and Temp Functions \r\n");
         //status = fuelGauge.forcedExitHyberMode();
@@ -548,6 +507,10 @@
         wait(1.0);
     
         displayOled.startscrollright(0x00, 0x0F);
+        
+        
+        uint32_t OLED_COUNT;
+        
     #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
         // No oled on the MAX32620FTHR
     #endif
@@ -715,74 +678,77 @@
                     pc.printf("Byte #%d is: %d\n", idx, max17055_u.curr_MAX17055_from_slave[idx]);
                 }
             #endif
-            if( memcmp(prev_MAX17055_from_slave, curr_MAX17055_from_slave, sizeof(curr_MAX17055_from_slave)) != 0 )
-            {
-                // Stop the scrolling to allow for a static image to be displayed on OLED
-                displayOled.stopscroll();
-                
-                displayOled.clearDisplay();
-
-                if ( chrg_status == false){
-                    if (max17055_u.battery.soc_FG >= 89)
-                        displayOled.drawBitmap(96,0,battFull,32,16,1);
-                    else if (max17055_u.battery.soc_FG >= 65 && max17055_u.battery.soc_FG < 89)
-                        displayOled.drawBitmap(96,0,batt75,32,16,1);
-                    else if (max17055_u.battery.soc_FG >= 45 && max17055_u.battery.soc_FG < 65)
-                        displayOled.drawBitmap(96,0,batt50,32,16,1);
-                    else if (max17055_u.battery.soc_FG >= 20 && max17055_u.battery.soc_FG < 45)
-                        displayOled.drawBitmap(96,0,batt25,32,16,1);
-                    else 
-                        displayOled.drawBitmap(96,0,battEmpty,32,16,1);
-                }
-
-                if (chrg_status == true){
-                    displayOled.drawBitmap(96,0,battChrging,32,16,1);
-                }
-
+            OLED_COUNT = OLED_COUNT + 1;
+            if( OLED_COUNT % OLED_FREQ == 0) {
+                if( memcmp(prev_MAX17055_from_slave, curr_MAX17055_from_slave, sizeof(curr_MAX17055_from_slave)) != 0 )
+                {
+                    // Stop the scrolling to allow for a static image to be displayed on OLED
+                    displayOled.stopscroll();
+                    
+                    displayOled.clearDisplay();
+    
+//                    if ( chrg_status == false){
+//                        if (max17055_u.battery.soc_FG >= 89)
+//                            displayOled.drawBitmap(96,0,battFull,32,16,1);
+//                        else if (max17055_u.battery.soc_FG >= 65 && max17055_u.battery.soc_FG < 89)
+//                            displayOled.drawBitmap(96,0,batt75,32,16,1);
+//                        else if (max17055_u.battery.soc_FG >= 45 && max17055_u.battery.soc_FG < 65)
+//                            displayOled.drawBitmap(96,0,batt50,32,16,1);
+//                        else if (max17055_u.battery.soc_FG >= 20 && max17055_u.battery.soc_FG < 45)
+//                            displayOled.drawBitmap(96,0,batt25,32,16,1);
+//                        else 
+//                            displayOled.drawBitmap(96,0,battEmpty,32,16,1);
+//                    }
+    
+                    if (chrg_status == true){
+                        displayOled.drawBitmap(96,0,battChrging,32,16,1);
+                    }
+    
+                    
+                    //serial.printf("Time to Empty= %dsec \r\n",tte_FG);
+                    int tte_minutes = (max17055_u.battery.tte_FG/60);
+                    int ttf_minutes = (max17055_u.battery.tte_FG/60);
+                    //serial.printf("Time to Empty= %dhours \r\n",tte_FG); 
+                    //serial.printf("Temp Function Status= %X \r\n",status);
+                    //wait(1);
+                    //serial.printf("SOC = %d %% \r\n",soc_FG);
+                    //serial.printf("Temp Function Status= %X \r\n",status);
+                    //serial.printf("Current = %d uamp \r\n",curr_FG);
+    //                pc.printf("Voltage = %d uvolts \r\n",max17055_u.battery.vcell_FG);
+                    int oper_f1 = max17055_u.battery.vcell_FG /1000000;
+                    int volt_mod_FG = (max17055_u.battery.vcell_FG % 1000000)/1000;
+    
+    //                pc.printf("Voltage = %d V \r\n",max17055_u.battery.vcell_FG);
+    //                pc.printf("Voltage = %d V \r\n",oper_f1);
+    
+    
+    
+                    displayOled.setTextCursor(0,0);
+                    displayOled.setTextColor(1);
+                    displayOled.setTextSize(1);
+                    //displayOled.setTextWrap(true);
+                    displayOled.printf("MAX17055");
+                    displayOled.setTextCursor(0,8);
+                    displayOled.printf("SOC = %d%% \r\n",max17055_u.battery.avg_soc_FG);
                 
-                //serial.printf("Time to Empty= %dsec \r\n",tte_FG);
-                int tte_minutes = (max17055_u.battery.tte_FG/60);
-                int ttf_minutes = (max17055_u.battery.tte_FG/60);
-                //serial.printf("Time to Empty= %dhours \r\n",tte_FG); 
-                //serial.printf("Temp Function Status= %X \r\n",status);
-                //wait(1);
-                //serial.printf("SOC = %d %% \r\n",soc_FG);
-                //serial.printf("Temp Function Status= %X \r\n",status);
-                //serial.printf("Current = %d uamp \r\n",curr_FG);
-//                pc.printf("Voltage = %d uvolts \r\n",max17055_u.battery.vcell_FG);
-                int oper_f1 = max17055_u.battery.vcell_FG /1000000;
-                int volt_mod_FG = (max17055_u.battery.vcell_FG % 1000000)/1000;
-
-//                pc.printf("Voltage = %d V \r\n",max17055_u.battery.vcell_FG);
-//                pc.printf("Voltage = %d V \r\n",oper_f1);
-
-
-
-                displayOled.setTextCursor(0,0);
-                displayOled.setTextColor(1);
-                displayOled.setTextSize(1);
-                //displayOled.setTextWrap(true);
-                displayOled.printf("MAX17055");
-                displayOled.setTextCursor(0,8);
-                displayOled.printf("SOC = %d%% \r\n",max17055_u.battery.avg_soc_FG);
-            
-                displayOled.setTextCursor(0,16);
-                if (chrg_status == true){    
-                    displayOled.printf("TTF = %dmins \r\n",tte_minutes);
-                }else 
-                    displayOled.printf("TTE = %dmins \r\n",tte_minutes);
-                displayOled.setTextCursor(0,24);
-                displayOled.printf("I=%duA \r\n",max17055_u.battery.avg_curr_FG);
-                displayOled.setTextCursor(65,24);
-                if (volt_mod_FG > 99){
-                    displayOled.printf("V=%d.%dV \r\n",oper_f1,volt_mod_FG);
-                }else if (volt_mod_FG < 100){
-                    displayOled.printf("V=%d.0%dV \r\n",oper_f1,volt_mod_FG);   
+                    displayOled.setTextCursor(0,16);
+                    if (chrg_status == true){    
+                        displayOled.printf("TTF = %dmins \r\n",tte_minutes);
+                    }else 
+                        displayOled.printf("TTE = %dmins \r\n",tte_minutes);
+                    displayOled.setTextCursor(0,24);
+//                    displayOled.printf("I=%dmA \r\n",max17055_u.battery.avg_curr_FG/1000);
+//                    displayOled.setTextCursor(65,24);
+                    if (volt_mod_FG > 99){
+                        displayOled.printf("V=%d.%dV \r\n",oper_f1,volt_mod_FG);
+                    }else if (volt_mod_FG < 100){
+                        displayOled.printf("V=%d.0%dV \r\n",oper_f1,volt_mod_FG);   
+                    }
+                    
+                    displayOled.display();
+                    displayOled.display();            
                 }
-                
-                displayOled.display();
-                displayOled.display();            
-            }        
+            }
         #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot    
             max17055_u.battery.soc_FG      = fuelGauge.get_SOC();
             max17055_u.battery.avg_soc_FG  = fuelGauge.get_atAvSOC(); 
@@ -809,7 +775,7 @@
         #endif
         
         /***************************************************************************
-         * Fill Payload Buffer With Data From Sensors for LoRa Transmition
+         * Fill Payload Buffer With Data From Main Program Buffers for next LoRa Transmition
          **************************************************************************/
         #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
             memcpy(&BufferTx[tx_idx_signature], PingMsg,           size_signature);
@@ -822,16 +788,14 @@
             memcpy(&BufferTx[tx_idx_MAX77650],  curr_MAX77650_to_master,  size_of_MAX77650);
         #endif
         
-        
-        
-        
+
         /***************************************************************************
          * Lora Communications
          **************************************************************************/
         SX1276PingPong();
         
         /***************************************************************************
-         * Fill Global Buffers With Data From Received Payload Buffer
+         * Fill Main Program Buffers With Data From Received Payload Buffer
          **************************************************************************/
         /* The master and slave devices will have different requirements for offloading payload */
         #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
@@ -851,15 +815,76 @@
         #if   defined(TARGET_MAX32630FTHR) // Master Device: BLE-to-LoRa Gateway
             // No motor controller on master
         #elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
+            /* This helps prevent devices such as robots that are connected over 
+             * LoRa from not receiving a stop message. This can help prevent 
+             * situations where a robot received a command to move in a dirrection
+             * but then moved to an area where it cant reliably receive communications.
+             * This situation would prevent a robot from stopping if it cant receive
+             * communications. So this is used to stop the current movement if the 
+             * robot is still moving after x amount of RxTimeouts have happened 
+             * in the LoRa communications. 
+             */
+            if (numOfRxTimeouts() >= NUM_TIMEOUTS_TO_STOP_ROBOT)
+            {
+                uint8_t simulate_release_button[2];
+                simulate_release_button[0] = curr_ble_from_master[0];
+                simulate_release_button[1] = 0;
+                MotorController(simulate_release_button);
+            }
+            
             // Check to see if the contents of the previous ble sdata received are the same. If they are different then change motor controllers registers
-            if( memcmp(prev_ble_from_master, curr_ble_from_master, sizeof(curr_ble_from_master)) != 0 )
+            else if( memcmp(prev_ble_from_master, curr_ble_from_master, sizeof(curr_ble_from_master)) != 0 )
             {
                 MotorController(curr_ble_from_master);
+                memcpy(prev_ble_from_master, curr_ble_from_master, sizeof(curr_ble_from_master));
             }
-        #endif
-        
-        
-        
+             
+        #endif   
+    }
+}
+
+
+/***************************************************************************
+ * MAX77650 Additional Functions
+ **************************************************************************/
+#if   defined(TARGET_MAX32630FTHR) // Master Device: MAX32630FTHR BLE-to-LoRa Gateway
+    // No MAX77650 PMIC on this board
+#elif defined(TARGET_MAX32620FTHR) // Slave Device: LoRa Controlled Robot
+    void charger_Detect() 
+    {
+        uint8_t int_chr_value,temp, int_chr_MASK = 0x04;         
+        int status; 
+        pc.printf("Charger Detected \n");
+        status = simo_pmic.readReg(MAX77650::INT_CHG, int_chr_value);
+        pc.printf("INT_CHR val= %X  \n", int_chr_value);
+        if (status == 1){
+            temp = int_chr_value & int_chr_MASK;
+            pc.printf("INT_CHR anded= %X  \n", temp);
+            if (temp == 4) 
+            {
+                pc.printf("enable charger \n");
+                simo_pmic.enCharger();
+            }
+        }
     }
     
-}
+    bool chrg_State_fn()
+    {
+        uint8_t status_chr_value,temp, chr_status_MASK = 0x02;         
+        int status; 
+        pc.printf("Charger State \n");
+        status = simo_pmic.readReg(MAX77650::STAT_CHG_B, status_chr_value);
+        pc.printf("STAR_CHG_B val= %X  \n", status_chr_value);
+        if (status == 1)
+        {
+            temp = status_chr_value & chr_status_MASK;
+            pc.printf("STAR_CHG_B val= %X  \n", temp);
+            if (temp == 2){
+                return true; 
+            }
+            return false; 
+        }
+        return false;
+    }
+    
+#endif