https://www.hackster.io/PSoC_Rocks/water-quality-monitoring-autonomous-robot-0bbf88

Dependencies:   BLE_API MAG3110 MMA8652 PID mbed nRF51822

Fork of uBit_BLE_UART_Voltmeter_IoT by Shahariar Hossain

Revision:
12:0777ec4114c8
Parent:
11:6916c05fde52
--- a/main.cpp	Fri Sep 07 20:17:07 2018 +0000
+++ b/main.cpp	Mon Oct 29 19:05:11 2018 +0000
@@ -1,4 +1,4 @@
-/* mbed Microcontroller Library
+/* mbed MicrocontrollerLL Library
  * Copyright (c) 2006-2013 ARM Limited
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
  //////////////////////////////////////////////////////////
 ///////////////////////NOTE ///////////////////////////////
 // This program uses BBC microbit as a NRF51822 board    //
@@ -20,9 +21,16 @@
 // BLE-uart/ADC/DIO/PWM capability, see pin maping below //
 ///////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////
+//////////////////////BLE WATER BOT/////////////////////////
+////////////////////////////////////////////////////////////
+
+
         
 #include <string.h>
 #include "mbed.h"
+#include "PID.h"
 #include "BLE.h"
 #include "stdio.h"
 #include "UARTService.h"
@@ -34,6 +42,13 @@
 #include "ConfigParamsPersistence.h"
 
 
+#include "math.h"
+#include "MAG3110.h"
+
+
+ 
+#define INTERVAL 0.1
+
 #define NEED_CONSOLE_OUTPUT 1 // if BLE printf messages needed on the remote console (PC/phone/host);                            
 #if NEED_CONSOLE_OUTPUT
 #define blePrintf(STR) { if (uart) uart->write(STR, strlen(STR)); }
@@ -43,38 +58,71 @@
 
 ///////////////// pin table /////////////////////////
 /////////////////////////////////////////////////////
-// ubit.pin    nrf51822pin    functions      note  //
+// edge.pin    nrf51822pin    functions      note  //
 /////////////////////////////////////////////////////
 //  P2           P0_1        ADC/PWM/DIO      2    //
 //  P1           P0_2        ADC/PWM/DIO      1    // 
 //  P0           P0_3        ADC/PWM/DIO      0    //
+//  P4           P0_5            ADC        COL 2  //
+//  P10          P0_6            ADC        COL 3  //
 //  P16          P_16            DIO               //
 //  P14          P0_25       SPI MIS/DIO           //
 //  P5           P_17        Button A/DI    pullup //
 //  P11          P_26        Button B/DI    pullup //
-
-/////////////////////////////////////////////////////
-///////////////// not mapped yet ////////////////////
-//  P20                      I2C SDA/DIO    pullup //
-//  P19                      I2C SCL/DIO    pullup //
+//  P20          P0_30       I2C SDA/DIO    pullup //
+//  P19          P0_0        I2C SCL/DIO    pullup //
 //  P15                      SPI MOS/DIO           //
 //  P13                      SPI SCK/DIO           //
-//  P16                                            //
-//  P8                                             //
 
 /////////////////////////////////////////////////////
-//      LED Matrix pins are not mapped             //
+//                  LED Matrix pins                //
+//  ROW 1  P0_13   ROW 2  P0_14   ROW 3  P0_15     //
+//  COL 1  P0_4    COL 2  P0_5    COL 3  P0_6      //
+//  COL 4  P0_7    COL 5  P0_8    COL 6  P0_9      //
+//  COL 7  P0_10   COL 8  P0_11   COL 9  P0_12     //
 /////////////////////////////////////////////////////
+/////////// See uBit to nrf51822 Schematic for detailed pinout //////////////////////
+// https://github.com/bbcmicrobit/hardware/blob/master/SCH_BBC-Microbit_V1.3B.pdf  //
+/////////////////////////////////////////////////////////////////////////////////////
+  //Kc, Ti, Td, interval
+          PID controllerL(1.0, 0.1, 0.1, INTERVAL);
+          PID controllerR(1.0, 0.1, 0.1, INTERVAL);
+          
+
 
 
+// Fan drive pwm
+
+PwmOut   LP(P0_2); // left propeller
+PwmOut   RP(P0_1); // right propeller
+
+MAG3110 mag(P0_30, P0_0); // set i2c pins SDA, SCL here //
 BLEDevice  ble;
-DigitalOut led1(LED1);
 UARTService *uart;
-AnalogIn   ain(P0_3);
+ 
+AnalogIn   temperature(P0_3); 
+AnalogIn   turbidity(P0_5);
+AnalogIn   conductivity(P0_6);
+
+DigitalOut   row1(P0_13);  // uBit 1st LED cathode 
+DigitalOut   col1(P0_4); // uBit 1st LED anode
+DigitalIn    swA(P0_17); // uBit button A
+//  col2(P0_5); // adc pin now led removed
+//  col3(P0_6); // adc pin now led removed
+
+//DigitalOut   col1(P0_4);
+
+
 int val,dVal, dec, i;
+int blepush = 0; 
+int refupdate = 0;
 char result[100];
-float batt = 0.03;
- 
+float TEMP = 0.0;
+float TURB = 0.0;
+float COND = 0.0;
+
+float heading = 0.0; // magnetometer heading
+float heading_ref = 0.0;
 
 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
 {
@@ -83,18 +131,60 @@
 
 void periodicCallback(void)
 {
+    blepush = 1;
+   // blePrintf("heading ");
+   // blePrintf(result);
+   // blePrintf("\r\n");
+}
+
+void navigationAdjust (void)
+{
     
-    blePrintf("BATT VOlT: ");
-    blePrintf(result);
-    blePrintf("\r\n");
 }
 
+void calXY() //magnetometer calibration: finding max and min of X, Y axis
+{
+    int tempXmax, tempXmin, tempYmax, tempYmin, newX, newY;
+
+    wait(3);
+
+    tempXmax = tempXmin = mag.readVal(MAG_OUT_X_MSB);
+    tempYmax = tempYmin = mag.readVal(MAG_OUT_Y_MSB);
+    int sample = 0;
+     
+    while(sample<501) {
+        wait(0.05);
+        newX = mag.readVal(MAG_OUT_X_MSB);
+        newY = mag.readVal(MAG_OUT_Y_MSB);
+        if (newX > tempXmax) tempXmax = newX;
+        if (newX < tempXmin) tempXmin = newX;
+        if (newY > tempYmax) tempYmax = newY;
+        if (newY < tempYmin) tempYmin = newY;
+        sample++;
+    col1.write(!(col1.read()));
+    //col3.write(!(col3.read()));
+    
+    }
+   
+    mag.setCalibration( tempXmin, tempXmax, tempYmin, tempYmax );
+ 
+
+}
+
+
 int main(void)
 {
-    Ticker ticker;
-    ticker.attach(periodicCallback, 5);
+    //  pwm freq
+    LP.period(0.01f); 
+    RP.period(0.01f);
+    LP.write(1.0);
+    RP.write(1.0);
+    wait(1);
+    LP.write(0.0);
+    RP.write(0.0);
 
-    blePrintf("Initialising the nRF51822\n\r");
+   row1.write(1);
+ 
     ble.init();
     ble.onDisconnection(disconnectionCallback);
     
@@ -111,28 +201,196 @@
 
     ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
     ble.startAdvertising();
+    
+
+    // may necessary //
+    while(swA.read())
+    {
+    ble.waitForEvent();
+    col1.write(!(col1.read()));
+    wait(1);
+    blePrintf("Hold A to start\n");
+    }
+  // max 20 Character at a time over BLE
+  // max 20 Character at a time over BLE
+  // max 20 Character at a time over BLE
+  
+    
+   ble.waitForEvent();   
+   blePrintf("Init  nRF51822  \n");
+   blePrintf("Calibrating Sensors\n");
+   blePrintf("Rotate To Calibrate\n");
+   blePrintf("when LED blinks fast\n");
+  
+    calXY(); // do the mag calib
+    ble.waitForEvent();
+    
+   blePrintf("Calibrate Completed\n");
+   blePrintf("Put Robot on Water\n");
+  
+    while(swA.read())
+    {
+        col1.write(!(col1.read()));
+        wait(1);
+        blePrintf("Hold A to proceed\n");
+  
+    }
+    
+    Ticker ticker;
+    ticker.attach(&periodicCallback, 5);
+
+    Ticker ticker2;
+    ticker2.attach(&navigationAdjust, .5);
+    
+ 
+  //Reference angle input from 0.0 to 3.3V
+  controllerL.setInputLimits(0.0, 360.0);
+  controllerR.setInputLimits(0.0, 360.0);
+ 
+  //Pwm output from 0.0 to 1.0
+  controllerL.setOutputLimits(0.0, 1.0);
+  controllerR.setOutputLimits(0.0, 1.0);
+  
+  //If there's a bias.
+  controllerL.setBias(0.0);
+  controllerR.setBias(0.0);
+  
+  controllerL.setMode(AUTO_MODE);
+  controllerR.setMode(AUTO_MODE);
+
+  //process variable or heading to be 90
+  controllerL.setSetPoint(90.0);
+  controllerR.setSetPoint(90.0);
+  
+ 
 
     while (true) {
         ble.waitForEvent();
-        val = ain.read_u16();
+            heading_ref = mag.getHeading();
+       if (heading_ref<0.0) heading_ref = heading_ref+360.00;
+       if (heading_ref>360.00) heading_ref = heading_ref -360.00;
+       controllerL.setProcessValue(heading_ref);
+       controllerR.setProcessValue(heading_ref);
+       float LPwr = controllerL.compute();
+       float RPwr = controllerR.compute();
+       //////////////////////////////////
+       //////////////////////////////////
+       //// WORKS BETTER THAN PID //////
+       //////////////////////////////////
+      ndr:
+      
+      if(refupdate == 1)
+      {
+       while(heading_ref != heading)
+       {
+        heading = mag.getHeading();
+       if (heading<0.0) heading_ref = heading+360.00;
+       if (heading>360.00) heading_ref = heading -360.00;
+       LP.write(.9);
+        }   
+       }
+      
+       
+       heading = heading_ref;
+       
+       for (int z =0;z<10;z++)
+       {
+       if (heading> heading_ref+2.0)
+       LP.write((heading - 90.0)/20.0);
+       else
+       LP.write(.0);   
+       wait(0.2);
+       
+       if (heading> heading_ref+2.0)
+       RP.write(( 90 - heading )/20.0);
+       else
+       RP.write(.0);   
+       wait(0.2);
+       LP.write(.7);   
+       RP.write(.7);   
+       wait(0.2);
+       
+       
+       }
+       /// heading is corrected after this line ///
+       /// calib may needed //
+
+    // val = ain.read_u16();
     // 22k+100K VOLTAGE DIVIDER AND 0.15 IS OFFSET   
-    batt = (122/22)*3.6*val/1023.0 - 0.15
-    dVal = batt;
-    dec = (int)(batt * 100) % 100;
+    // batt = (122/22)*3.6*val/1023.0 - 0.15
+    
+    //Update the process variable.
+    //Set the new output.
+ 
+      
+  if (blepush ==1)
+  {
+    
+    TEMP = 3.3*100*temperature.read_u16()/(5*1023); // 10 mV= 1 deg c, vcc =3.3 v, Opamp gain 5
+    dVal = TEMP;
+    dec = (int)(TEMP * 100) % 100;
 
     memset(result, 0, 100);
-    result[0] = (dVal / 10) + '0';
-    result[1] = (dVal % 10) + '0';
-    result[2] = '.';
-    result[3] = (dec / 10) + '0';
-    result[4] = (dec % 10) + '0';
-
-
+    
+    result[0] = (dVal / 100) + '0';
+    result[1] = ((dVal / 10)%10) + '0';
+    result[2] = (dVal % 10) + '0';
+    result[3] = '.';
+    result[4] = (dec / 10) + '0';
+    result[5] = (dec % 10) + '0';
     for (i=strlen(result)-1; i>=0; i--)
         putc(result[i], stdout);
-      
-            }
-}
+    
+    blePrintf("temperature ");
+    blePrintf(result);
+    blePrintf("\n");  
+
+    TURB = 3.3*10*turbidity.read_u16()/1023; // fix gain later
+    dVal = TURB;
+    dec = (int)(TURB * 100) % 100;
+
+    memset(result, 0, 100);
+    
+    result[0] = (dVal / 100) + '0';
+    result[1] = ((dVal / 10)%10) + '0';
+    result[2] = (dVal % 10) + '0';
+    result[3] = '.';
+    result[4] = (dec / 10) + '0';
+    result[5] = (dec % 10) + '0';
+    for (i=strlen(result)-1; i>=0; i--)
+        putc(result[i], stdout);
+    
+    blePrintf("turbidity ");
+    blePrintf(result);
+    blePrintf("\n");  
 
 
 
+    COND = 3.3*10*conductivity.read_u16()/1023; // fix gain later
+    dVal = COND;
+    dec = (int)(COND * 100) % 100;
+
+    memset(result, 0, 100);
+    
+    result[0] = (dVal / 100) + '0';
+    result[1] = ((dVal / 10)%10) + '0';
+    result[2] = (dVal % 10) + '0';
+    result[3] = '.';
+    result[4] = (dec / 10) + '0';
+    result[5] = (dec % 10) + '0';
+    for (i=strlen(result)-1; i>=0; i--)
+        putc(result[i], stdout);
+    
+    blePrintf("conductivity ");
+    blePrintf(result);
+    blePrintf("\n");  
+   blepush =0;
+   }
+      goto ndr;
+            }
+// end of while(1)            
+}
+// end of main()
+
+
+