Starting point for the student buggy project

Dependencies:   microbit

Fork of microbit-hello-world by micro:bit

Revision:
2:47b7a55b0805
Child:
4:2d939ef2b09c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Buggy.cpp	Mon Jul 31 21:48:36 2017 +0000
@@ -0,0 +1,384 @@
+/***********************************************************************
+This file contains the different function calls that can be used to control
+the buggy and read and control the ultrasonic sensor on the buggy
+*************************************************************************/
+/************
+Includes
+**************/
+#include "Buggy.h"
+#include <stdio.h>
+
+/******************
+Definition of constants
+******************/
+#define BUGGY_HALTED    0
+#define BUGGY_RUNNING   1
+#define BUGGY_PAUSED    2
+
+/*******************************
+Local function declarations
+*******************************/
+void onSonarEchoPulse(MicroBitEvent evt);
+void MoveForward(unsigned int Voltage, unsigned int Time_ms);
+void MoveBackward(unsigned int Voltage, unsigned int Time_ms);
+void RotateClockwise(unsigned int Voltage, unsigned int Time_ms);
+void RotateAnticlockwise(unsigned int Voltage, unsigned int Time_ms);
+void SendSonarTrigger();
+
+/*******************************
+Global variables for the microbit runtime
+******************************/
+MicroBit uBit;
+MicroBitPin MotorSpeed_L(MICROBIT_ID_IO_P0, MICROBIT_PIN_P0, PIN_CAPABILITY_ANALOG);
+MicroBitPin MotorDirection_L(MICROBIT_ID_IO_P8, MICROBIT_PIN_P8, PIN_CAPABILITY_DIGITAL );
+MicroBitPin MotorSpeed_R(MICROBIT_ID_IO_P1, MICROBIT_PIN_P1, PIN_CAPABILITY_ANALOG);
+MicroBitPin MotorDirection_R(MICROBIT_ID_IO_P12, MICROBIT_PIN_P12, PIN_CAPABILITY_DIGITAL );
+//Note: The buggy has both the trigger and echo signals on the same microbit pin
+MicroBitPin Sonar(MICROBIT_ID_IO_P13, MICROBIT_PIN_P13, PIN_CAPABILITY_DIGITAL);
+ 
+
+/**********************************
+Global variables for the buggy interface
+*************************************/
+unsigned long SonarReturnPulseWidth = 0xFFFFFFFF;
+int TargetMotorRunTime = 0;
+int CurrentMotorRunTime = 0;
+unsigned int TimerStart = 0;
+unsigned int LastMotorVoltage_L = 0;
+unsigned int LastMotorVoltage_R = 0;
+unsigned int LastMotorDirection_L = 0;
+unsigned int LastMotorDirection_R = 0;
+int BuggyState = BUGGY_HALTED;
+Ticker SonarTriggerTimer;
+
+/*****************************************************************************
+Start of function definitions
+*****************************************************************************/
+void InitialiseBuggy()
+{
+    //Initialise the micro:bit runtime.
+    uBit.init();
+    
+    //setup the message bus to listen for events from the ultrasonic sensor input
+    uBit.messageBus.listen(MICROBIT_ID_IO_P13, MICROBIT_PIN_EVT_PULSE_HI, onSonarEchoPulse, MESSAGE_BUS_LISTENER_IMMEDIATE);
+    
+    //Attach the SendSonarTrigger function to the timer and configure for it to trigger every 0.2 secs.
+    SonarTriggerTimer.attach(&SendSonarTrigger, 0.2); 
+}
+
+void SendSonarTrigger()
+{
+    //Turn the monitoring of the event off whilst the trigger pulse is sent.
+    Sonar.eventOn(MICROBIT_PIN_EVENT_NONE);
+    /*Set the trigger to high for 10 microseconds, then back to a low. This
+    setDigitalValue function also changes the pin to an output pin*/
+    Sonar.setDigitalValue(1);
+    wait_us(10);
+    Sonar.setDigitalValue(0);
+    
+    //Call this function to turn the sonar pin back to an input pin to await the echo.
+    Sonar.getDigitalValue();
+    //Turn the event back on so that this function responds again
+    Sonar.eventOn(MICROBIT_PIN_EVENT_ON_PULSE);
+    
+    return;
+    
+}
+
+void onSonarEchoPulse(MicroBitEvent evt)
+{
+    //Read the pulse wdith of the returned echo.  This is returned in the timestamp of the event.
+    SonarReturnPulseWidth = evt.timestamp;
+    
+    return;
+}
+
+unsigned int GetSonarTime_us()
+{
+    return (unsigned int)SonarReturnPulseWidth;
+}
+
+bool hasLastCommandCompleted()
+{
+    if(BuggyState == BUGGY_RUNNING)
+    {
+        CurrentMotorRunTime = uBit.systemTime() - TimerStart;
+        if(CurrentMotorRunTime >= TargetMotorRunTime)
+        {
+            //Stop the motors by writing a 0 voltage and setting direction to forward.
+            MotorDirection_L.setDigitalValue(0);
+            MotorDirection_R.setDigitalValue(0);
+            MotorSpeed_L.setAnalogValue(0);  
+            MotorSpeed_R.setAnalogValue(0);
+            
+            //Update the buggy state to show that it is now halted
+            BuggyState = BUGGY_HALTED;
+            
+            //completed
+            return true;
+        }
+        else
+        {
+            //return not completed
+            return false;
+        }
+    }
+    
+    //return no last command was running
+    return false; 
+}
+
+void PauseLastCommand()
+{
+    //Only do this if the buggy is actually running
+    if(BuggyState == BUGGY_RUNNING)
+    {
+        //Store the amount of elapsed time before the command is paused.
+        CurrentMotorRunTime = uBit.systemTime() - TimerStart;
+        //Stop the motors by writing a 0 voltage and setting direction to forward.
+        MotorDirection_L.setDigitalValue(0);
+        MotorDirection_R.setDigitalValue(0);
+        MotorSpeed_L.setAnalogValue(0);  
+        MotorSpeed_R.setAnalogValue(0);
+        
+        //Update the buggy state to show that it is now halted
+        BuggyState = BUGGY_PAUSED;
+    }
+}
+
+void ContinueLastCommand()
+{
+    //Only do this if the buggy is currently halted we have not yet reached the target run time
+    if( (BuggyState == BUGGY_PAUSED) && (TargetMotorRunTime > CurrentMotorRunTime) )
+    {
+        //Update the target motor run time to only run for the incomplete time period and zero CurrentMotorRunTime
+        TargetMotorRunTime = TargetMotorRunTime - CurrentMotorRunTime;
+        CurrentMotorRunTime = 0;
+        //Set the voltage of the motors as per the stored last voltage and direction command.
+        MotorDirection_L.setDigitalValue(LastMotorDirection_L);
+        MotorDirection_R.setDigitalValue(LastMotorDirection_R);
+        MotorSpeed_L.setAnalogValue(LastMotorVoltage_L);  
+        MotorSpeed_R.setAnalogValue(LastMotorVoltage_R); 
+        
+        //Start the timer
+        TimerStart = uBit.systemTime();
+        
+        //Update the buggy state to show that it is now running
+        BuggyState = BUGGY_RUNNING;
+    }
+}
+
+void MoveBuggy(int Command, unsigned int Voltage, unsigned int Time_ms)
+{
+    //Initialise the variables for tracking the travel progress
+    TargetMotorRunTime = Time_ms;
+    CurrentMotorRunTime = 0;
+    
+    //Limit the voltage to 1024, which is the max A2D output value.
+    if(Voltage > 1024)
+    {
+        Voltage = 1024;
+    }
+    
+    switch(Command)
+    {
+        case MOVE_FORWARD:
+            //Set the motor voltage as requested by the user
+            LastMotorVoltage_L = Voltage;
+            LastMotorVoltage_R = Voltage;
+            //Set motor direction to forward
+            LastMotorDirection_L = 0;
+            LastMotorDirection_R = 0; 
+            break;
+            
+        case MOVE_BACKWARD:
+            /*Set the voltage of the motors as per the user request (1024 - value)
+            In reverse, 0 is actually max speed and 1024 is stopped.*/
+            LastMotorVoltage_L = 1024 - Voltage;
+            LastMotorVoltage_R = 1024 - Voltage;
+            //Set the motor direction to reverse
+            LastMotorDirection_L = 1;
+            LastMotorDirection_R = 1;
+            break;
+            
+        case ROTATE_CLOCKWISE:
+            /*Set the voltage of the motors as per the user request (1024 - value)
+            In reverse, 0 is actually max speed and 1024 is stopped.*/
+            LastMotorVoltage_L = Voltage;
+            LastMotorVoltage_R = 1024 - Voltage;
+            //Set the direction to left wheel forwards and right wheel backward
+            LastMotorDirection_L = 0;
+            LastMotorDirection_R = 1;
+            break;
+            
+        case ROTATE_ANTICLOCKWISE:
+            /*Set the voltage of the motors as per the user request (1024 - value)
+            In reverse, 0 is actually max speed and 1024 is stopped.*/
+            LastMotorVoltage_L = 1024 - Voltage;
+            LastMotorVoltage_R = Voltage;
+            //Set the direction to left wheel backwards and right wheel forward
+            LastMotorDirection_L = 1;
+            LastMotorDirection_R = 0;
+            break;
+            
+        default:
+        
+            break;    
+    }
+    
+    //Set the direction of the motors as per the command
+    MotorDirection_L.setDigitalValue(LastMotorDirection_L);
+    MotorDirection_R.setDigitalValue(LastMotorDirection_R);
+    wait_ms(1);
+    //Set the voltage of the motors as per the user request 
+    MotorSpeed_L.setAnalogValue(LastMotorVoltage_L);  
+    MotorSpeed_R.setAnalogValue(LastMotorVoltage_R); 
+    
+    //Start the timer
+    TimerStart = uBit.systemTime();
+    
+    //Update the buggy state to show that it is now running
+    BuggyState = BUGGY_RUNNING;
+    
+    return;
+}
+
+
+void RunBasicBuggyMotorTest(unsigned int Voltage, unsigned int Time_ms, unsigned int Pause_ms)
+{
+    //Move the buggy forward
+    MoveBuggy(MOVE_FORWARD, Voltage, Time_ms);
+    //wait and check if the command has completed
+    do
+    {
+        //sleep whilst we wait for the command to complete
+        uBit.sleep(Time_ms);
+    }while( hasLastCommandCompleted() == false );
+    //Pause before doing the next command
+    wait_ms(Pause_ms);
+    
+    //Move the buggy bacward    
+    MoveBuggy(MOVE_BACKWARD, Voltage, Time_ms);
+    //wait and check if the command has completed
+    do
+    {
+        //sleep whilst we wait for the command to complete
+        uBit.sleep(Time_ms);
+    }while( hasLastCommandCompleted() == false );
+    //Pause before doing the next command
+    wait_ms(Pause_ms);
+    
+    //Rotate the buggy clockwise
+    MoveBuggy(ROTATE_CLOCKWISE, Voltage, Time_ms);
+    //wait and check if the command has completed
+    do
+    {
+        //sleep whilst we wait for the command to complete
+        uBit.sleep(Time_ms);
+    }while( hasLastCommandCompleted() == false );
+    //Pause before doing the next command
+    wait_ms(Pause_ms);
+    
+    //Rotate the buggy anticloclwise
+    MoveBuggy(ROTATE_ANTICLOCKWISE, Voltage, Time_ms);
+    //wait and check if the command has completed
+    do
+    {
+        //sleep whilst we wait for the command to complete
+        uBit.sleep(Time_ms);
+    }while( hasLastCommandCompleted() == false );
+    //Pause before doing the next command
+    wait_ms(Pause_ms);
+    
+    return;
+}
+
+void TestAntiCollision(unsigned int Voltage, unsigned int Time_ms, unsigned int SonarTime_us)
+{
+    MoveBuggy(MOVE_FORWARD, Voltage, Time_ms);
+    do
+    {
+        if(GetSonarTime_us() < SonarTime_us)
+        {
+            PauseLastCommand();
+        }
+        else
+        {
+            ContinueLastCommand();
+        }
+    }while( hasLastCommandCompleted() == false );
+    
+    return;
+    
+}
+
+void TestSonar()
+{
+    //Local variables
+    MicroBitImage SonarImage;
+    unsigned int SonarDistance;
+    int NumPixels, x, y;
+    int MaxDisplayDist = 100;
+    int WholeRows, RemainderColumns;
+       
+    //Compute the distance in cm. the 58 is taken from the datasheet
+    SonarDistance = GetSonarTime_us()/58;
+    //limit to 1m
+    if(SonarDistance > MaxDisplayDist)
+    {
+        SonarDistance = MaxDisplayDist;   
+    }
+       
+    //Convert the distance to the number of pixels to light
+    NumPixels = (SonarDistance*25)/MaxDisplayDist;
+    //Convert into the number of whole pixel rows and remainder columns to light
+    WholeRows = NumPixels/5;
+    RemainderColumns = NumPixels%5;
+   
+    //First fill the whole rows
+    for(y=0; y<WholeRows; y++)
+    {
+        for(x=0; x<5; x++)
+        {
+            uBit.display.image.setPixelValue(x, y, 200);
+        }
+    }
+
+    //fill the partial row
+    if(WholeRows < 5)
+    {
+        for(x=0; x<RemainderColumns; x++)
+        {
+            uBit.display.image.setPixelValue(x, y, 200);
+        }
+    }
+    
+    //Fill the remaining pixels in the partial row with 0
+    for( ; x<5; x++)
+    {
+        uBit.display.image.setPixelValue(x, y, 0);
+    }
+    //Continue from the next row
+    y++;
+    for( ; y<5; y++)
+    {
+        for(x=0; x<5; x++)
+        {
+            uBit.display.image.setPixelValue(x, y, 0);
+        }
+    }
+
+    return;
+}
+
+void PrintSonarTiming(void)
+{
+    //Local variables
+    int SonarTime;
+    
+    //read the latest sonar time
+    SonarTime = GetSonarTime_us();
+    //Print the time in micro secs
+    uBit.display.printAsync(SonarTime);
+    uBit.serial.printf("Time = %d us\n\r", SonarTime);
+}