Xbeat beta code as published by Andre Moehl ( http://mbed.org/users/hoppel/ ) With a slightly modified serial port definition

Dependencies:   mbed

Revision:
0:badcd0d61c7b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Feb 04 08:31:00 2011 +0000
@@ -0,0 +1,488 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file  main.c
+ * @author     andre moehl
+ * @date   01/2011
+ *
+ *
+ * Implements the main functionalty and als programs for the XBeat.
+ */
+
+/*--- Includes ------------------------------*/
+#include "mbed.h"
+#include "SRF05.h"
+#include "drive.h"
+#include "button.h"
+
+
+/*--- Defines -------------------------------*/
+#define DEBUG 1
+
+#define TTLSERIAL 1 //use the ttl(p13,p14) serial port or the native USB serial port if 0
+#define BAUDRATE 19200
+
+#define OFF 0
+#define ON 1
+
+// Battery measure
+#define UBAT_R_FACTOR 3.1363636 //resistor divider
+//#define UBAT_LOW 66       //6,6V 
+#define UBAT_LOW 72         //7,2V - more adequate value to protect lipos
+
+
+// Servo Zero Position Offset
+#define OFFSET_L -35
+#define OFFSET_R 45
+
+
+
+/*--- Global Variables ----------------------*/
+/* Hardware Definitions */
+DigitalOut led1(LED1);      ///< Leds on mbed board
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+DigitalOut Speaker(p12);    ///< Loudspeaker
+AnalogIn   ubat(p15);       ///< LiPo Voltage Measurement
+DigitalOut T6(p29);         ///< FET for Bottom IR-LEDs
+DigitalOut T7(p30);         ///< FET for Side IR-LEDs
+AnalogIn   IRL(p16);        ///< IR-Transistor Bottom Left
+AnalogIn   IRM(p17);        ///< IR-Transistor Bottom Middle
+AnalogIn   IRR(p18);        ///< IR-Transistor Bottom Right
+AnalogIn Left(p19);         ///< IR-Transistor Left Side
+AnalogIn Right(p20);        ///< IR-Transistor Right Side
+Button SW1(p10);            ///< Button Outer Side
+Button SW2(p9);             ///< Button Inner Side
+
+#ifdef TTLSERIAL
+Serial pc (p13,p14);        ///< Serial Interface via TTL Port
+#else
+Serial pc(USBTX, USBRX);  ///< Serial Intervace via USB Port (tx, rx)
+#endif
+
+/** Timer and Tickers */
+Ticker LiPoTicker;  //ticker for checking LiPoVoltage
+Ticker tick_1ms;    //Ticker for checking Button
+
+/*--- Flags ---------------------------------*/
+
+int SW1_state=0;    // Current State of SW1
+int SW1_old=0;      // Previous State of SW1
+int SW2_state=0;    // Current State of SW2
+int SW2_old=0;      // Previous State of SW2
+int start=0;        // indicate to start a program
+int stop=1;         // indicate to stop a program
+int programm_counter=1; // Counts the number of SW2 samples to select a program
+uint8_t firstUnderVoltage;  // set to 1 when the battery measure is first time under the limit
+
+
+/**--- predeclarared Functions --------------*/
+void setLed(int led);
+float getLiPoVoltage();
+
+/**--- Functions ----------------------------*/
+
+////// PROGRAMM LINE FOLLOW ///////////////////////////////////////////
+
+#define LFDUTYCYCLE 0.001
+/**
+* @brief Programm LineFollow follows lines on paper. Uses the IR-Transistors to detect.
+* @parameter mode Fast or Slow
+*/
+void LineFollow() {
+    Drive XBeat(p21,p22);                                       //Left, Right Servo Motor
+    int i;
+    int ML=0, MR=0;                                             //Motor set-points
+    int MaxSpeed=0;                                             ///< Maximum Speed in Percent
+    unsigned short left=0, right=0, mid=0;                      // current measured values
+    unsigned short  soll_left=0, soll_right=0, soll_mid=0;      // must values
+    signed int error_r=0,error_l=0,error_m=0;                   // setpoint errors
+    signed int prev_error_r=0, prev_error_l=0, prev_error_m=0;  // previous setpoint errors
+    signed int dmeas_r=0, dmeas_l=0, dmeas_m=0;                 // derive error
+    signed int pid_r=0, pid_l=0, pid_m=0;                       // calced controller values
+
+
+    MaxSpeed = 100;                                             //Set Maximum Line Follow Speed
+
+    pc.printf("Program \"Line Follow\"\n\r\n\r");
+    XBeat.setoffset(OFFSET_L,OFFSET_R);
+    T6 = ON; //switch IR-Leds on
+
+    //read values for calc the set point values
+    soll_left = IRL.read_u16()/100;
+    soll_right = IRM.read_u16()/100;
+    soll_mid = IRM.read_u16()/100;
+    for (i=30;i>0;i--) {
+        soll_left = (soll_left + IRL.read_u16()/100)/2;
+        soll_right = (soll_right + IRR.read_u16()/100)/2;
+        soll_mid = (soll_mid + IRM.read_u16()/100)/2;
+    }
+    //debug
+    pc.printf("Sollwert Links: %d\n\r", soll_left);
+    pc.printf("Sollwert Rechts: %d\n\r", soll_right);
+    wait(2);
+    //peep
+    Speaker = 1;
+    wait (0.1);
+    Speaker = 0;
+    //acceleration
+    int ms = 500/MaxSpeed;
+    for (i=0; i<MaxSpeed; i+=2) {
+        XBeat.move(i,i);
+        wait_ms(ms);
+    }
+
+    //drive until pressing stop button
+    while (!stop) {
+        //set SetPoint
+        MR = MaxSpeed;
+        ML = MaxSpeed;
+
+        //get sensor data
+        left = IRL.read_u16()/100;
+        right = IRR.read_u16()/100;
+        mid = IRM.read_u16()/100;
+
+        //calc controller (PD)
+        error_l = soll_left - left;
+        dmeas_l = (error_l - prev_error_l)/2;
+        prev_error_l = error_l;
+        error_r = soll_right - right;
+        dmeas_r = (error_r - prev_error_r)/2;
+        prev_error_r = error_r;
+        error_m = soll_mid - mid;
+        dmeas_m = (error_m - prev_error_m)/2;
+        prev_error_m = error_m;
+
+        pid_l = (2*error_l + dmeas_l)/20;
+        pid_r = (2*error_r + dmeas_r)/20;
+        pid_m = (2*error_m + dmeas_m)/10;
+
+        //Limit controller output
+        if (pid_l >= MaxSpeed) pid_l = MaxSpeed;
+        if (pid_l <= -MaxSpeed) pid_l = -MaxSpeed;
+        if (pid_r >= MaxSpeed) pid_r = MaxSpeed;
+        if (pid_r <= -MaxSpeed) pid_r = -MaxSpeed;
+        //debug
+        pc.printf("pidL %d, pidR%d\n\r", pid_l, pid_r);
+
+        if (pid_l > 2) ML = ML + pid_m;
+        if (pid_r > 2) MR = MR + pid_m;
+
+        ML = ML - pid_l;// - pid_r/2;
+        MR = MR - pid_r;// - pid_l/2;
+        if (ML > MaxSpeed) {
+            ML = MaxSpeed;
+            MR = MR + pid_l;
+        }
+        if (MR > MaxSpeed) {
+            MR = MaxSpeed;
+            ML = ML + pid_r;
+        }
+        //Bottom Limit Motor values
+        if (ML < -10) ML = -10;
+        if (MR < -10) MR = -10;
+
+        pc.printf("ML %d, MR%d\n\r", ML, MR);
+
+        //set Motor values
+        XBeat.move(ML, MR); //set motor speed
+        wait(LFDUTYCYCLE);
+    }
+    //Finished
+    T6 = OFF;
+    start = 0;
+    stop = 1;
+    pc.printf("Program \"Line Follow\" stopped\n\r");
+}
+
+////// PROGRAMM REMOTE CONTROL //////////////////////////////////////////
+
+/**
+* @brief Control the XBeat via remote
+*/
+void RemoteControl() {
+    Drive XBeat(p22,p21);       //Left, Right Servo Motor
+    pc.printf("Program \"Remote Control\" started\n\r");
+    XBeat.setoffset(OFFSET_L,OFFSET_R);
+    pc.printf("Currently not implemented.\n\r");
+    start = 0;
+    stop = 1;
+    pc.printf("Program \"Remote Control\" stopped\n\r");
+}
+
+
+////// PROGRAMM MAZE SOLVER /////////////////////////////////////////////
+
+#define MAZE_SPEED 60
+#define MAZEDUTYCYCLE 0.01
+/**
+ * @brief drives the XBeat thru a maze
+ * made for 27C3 Maze Logo
+ */
+void MazeSolver() {
+    Drive XBeat(p22,p21);       //Left, Right Servo Motor
+    pc.printf("Program \"Maze Solver\" started\n\r");
+    XBeat.setoffset(OFFSET_L,OFFSET_R);
+    pc.printf("The Implementation is currently not finished. I working on it and release this later.\n\r");
+    start = 0;
+    stop = 1;
+    pc.printf("Program \"Maze Solver\" stopped\n\r");
+}
+
+///// PROGRAMM DRIVE AND TURN /////////////////////////////////////////////
+
+void driver() {
+    SRF05 srf(p6, p5);          // Front Sensor
+    Drive XBeat(p21,p22);       // Left, Right Servo Motor
+    signed int m1=0,m2=0;       // Motor Set values
+    float front=0, front_old=0; // measured value from front sensor
+    int turn=0;                 // flag for indicate a turn
+    int ticks=0;                // loop counter for turn
+
+    pc.printf("\n\rJust Moving\n\r\n\r");
+    XBeat.setoffset(OFFSET_L,OFFSET_R);
+
+    while (!stop) {
+        if (!turn) {
+            if ((front < front_old) && (front > 8.0)) { //close to a front wall, slow stopping
+                if (m1 < 0) m1 = m1-1;
+                if (m2 < 0) m2 = m2-1;
+                pc.printf("1\n\r");
+            } else {
+                if (m1 < 100) m1++;
+                if (m2 < 100) m2++;
+            }
+            front_old = front;
+        }
+
+        if (turn) {
+            ticks++;
+            if (ticks <= 300) {
+                if (m1 < 50) m1++;
+                if (m2 > -50) m2--;
+            } else {
+                if (m1 >= 0) m1--;
+                if (m2 <= 0) m2++;
+                if (m1 == 0 || m2 == 0) {
+                    turn=0;
+                    ticks=0;
+                }
+            }
+        }
+
+        if (front < 8.0 && !turn) {
+            m1=0;
+            m2=0;
+            turn=1;
+            ticks=0;
+        }
+        XBeat.move(m1,m2);
+    }
+    start = 0;
+    stop = 1;
+    pc.printf("Program \"Driving\" stopped\n\r");
+}
+
+
+/////// Sensor Data ///////////////////////////////////////////////////////
+
+/**
+*   @brief Writing Sensor Data to UART, for debugging purpose
+*/
+void SensorData() {
+    SRF05 srf(p6, p5);
+    T6 = ON;
+    T7 = ON;
+    pc.printf("Sensor Data\n\r\n\r");
+    while (!stop) {
+        pc.printf("IR-Left %d, IR-Right %d, SRF05 %f\n\r", Left.read_u16()/100, Right.read_u16()/100, srf.read());
+        pc.printf("IRL %d, IRM %d, IRR %d\n\r", IRL.read_u16()/100, IRM.read_u16()/100, IRR.read_u16()/100);
+        pc.printf("LiPo Voltage %f\n\r\n\r", getLiPoVoltage() );
+        wait (1);
+    }
+    T7 = OFF;
+    T6 = OFF;
+    start = 0;
+    stop = 1;
+}
+
+
+/////// RECALLED FUNCTIONS ////////////////////////////////////
+/**
+ * @brief function called ervery 1ms to read the button states
+ */
+void checkButtons () {
+    //int c=0;
+    if (SW1) {
+        SW1_state = 1;
+    } else SW1_state = 0;
+    if (SW1_old == 1 && SW1_state == 0) {       //falling edge
+        /** Add Code to do when Button 1 is pressed */
+        start = !start;
+        stop = !start;
+    }
+    SW1_old = SW1_state;
+
+    if (SW2) SW2_state = 1;
+    else SW2_state = 0;
+    if (SW2_old == 1 && SW2_state == 0) {       //falling edge
+        /** Add Code to do when Button 2 is pressed */
+        if (stop) {
+            if (programm_counter < 5) programm_counter++;
+            else programm_counter = 1;
+
+            switch (programm_counter) {
+                case 1:
+                    pc.printf("Programm %d:  Line Follow\n\r", programm_counter );
+                    break;
+                case 2:
+                    pc.printf("Programm %d:  Maze Solver\n\r", programm_counter );
+                    break;
+                case 3:
+                    pc.printf("Programm %d:  Driving\n\r", programm_counter );
+                    break;
+                case 4:
+                    pc.printf("Programm %d:  Remote Control\n\r", programm_counter );
+                    break;
+                case 5:
+                    pc.printf("Programm %d:  Sensor Data\n\r", programm_counter );
+                    break;
+            }
+            if (programm_counter == 5) {
+                led1=1;
+                led4=1;
+            } else    setLed(programm_counter);
+        }
+    }
+    SW2_old = SW2_state;
+}
+
+
+
+/** @brief calculates the battery voltage
+*   @return real voltage als float */
+float getLiPoVoltage() {
+    return ((ubat*UBAT_R_FACTOR*3.3)+0.79);
+}
+
+/**@brief function called every 1s to check LiPo Voltage */
+void LiPo_Warning() {
+    int c = 0;
+    //LiPo Undervoltage Emergency Stop
+    if ((getLiPoVoltage()*10) < UBAT_LOW) {
+
+        start=0;
+        stop=1;
+        if (firstUnderVoltage) { //need to return 1st time to stop the motors
+            firstUnderVoltage = 0;
+            return;
+        } else {
+            while (1) { //stay here
+                Speaker = 1;
+                led4 = 1;
+                wait(0.1);
+                led4 = 0;
+                Speaker = 0;
+                wait(1);
+                if (c++ == 5) {
+                    pc.printf("LiPo Voltage: %fV\n\r",getLiPoVoltage());
+                    c=0;
+                }
+            }
+        }
+    }
+}
+
+//////// HELPER ///////////////////////////////////////////////////////////
+/** @ brief set the LEDs on the mbed dev board
+ * @parameter led - LED Number (1-4)
+ */
+void setLed(int led) {
+    led1=OFF;
+    led2=OFF;
+    led3=OFF;
+    led4=OFF;
+
+    switch (led) {
+        case 1:
+            led1 = ON;
+            break;
+        case 2:
+            led2 = ON;
+            break;
+        case 3:
+            led3 = ON;
+            break;
+        case 4:
+            led4 = ON;
+            break;
+    }
+}
+
+
+
+
+/** @brief Initializations */
+void init() {
+    pc.baud(BAUDRATE);                          //set uart baudrate
+    tick_1ms.attach_us(&checkButtons, 1000);    //ervery 1ms
+    firstUnderVoltage = 1;                      // set flag
+    LiPoTicker.attach(&LiPo_Warning,1);         //check LiPo voltage every second
+}
+
+///////// MAIN  ///////////////////////////////////////////////////////////
+
+/**
+*   @brief main function
+*/
+int main() {
+    init();
+    setLed(programm_counter);
+    pc.printf("---- XBeat ----\n\r\n\r");
+    pc.printf("Initial Program 1: Line Follow\n\r");
+    while (1) {
+        wait(0.1);
+        if (start) {
+            switch (programm_counter) {
+                case 1:
+                    LineFollow();
+                    setLed(programm_counter);
+                    break;
+                case 2:
+                    MazeSolver();
+                    setLed(programm_counter);
+                    break;
+                case 3:
+                    driver();
+                    setLed(programm_counter);
+                    break;
+                case 4:
+                    RemoteControl();
+                    setLed(programm_counter);
+                    break;
+                case 5:
+                    SensorData();
+                    setLed(programm_counter++);
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+}
+