Starting point for the student buggy project

Dependencies:   microbit

Fork of microbit-hello-world by micro:bit

Revision:
1:8c05eb53f714
Parent:
0:0041f35b0c4c
Child:
2:47b7a55b0805
--- a/main.cpp	Wed Jul 13 16:03:21 2016 +0100
+++ b/main.cpp	Sun Jul 16 20:23:27 2017 +0000
@@ -25,15 +25,402 @@
 
 #include "MicroBit.h"
 
+#define BUGGY_HALTED    0
+#define BUGGY_RUNNING   1
+#define BUGGY_PAUSED    2
+
+void onButtonA(MicroBitEvent);
+int main();
+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 PauseLastCommand();
+void ContinueLastCommand();
+bool hasLastCommandCompleted();
+
 MicroBit uBit;
 
+MicroBitButton buttonA(MICROBIT_PIN_BUTTON_A, MICROBIT_ID_BUTTON_A);
+MicroBitButton buttonB(MICROBIT_PIN_BUTTON_B, MICROBIT_ID_BUTTON_B);
+
+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 );
+
+//Sonar trigger and echo
+MicroBitPin Echo(MICROBIT_ID_IO_P13, MICROBIT_PIN_P13, PIN_CAPABILITY_DIGITAL);
+MicroBitPin Trig(MICROBIT_ID_IO_P13, MICROBIT_PIN_P13, PIN_CAPABILITY_DIGITAL);
+
+MicroBitMessageBus bus; 
+unsigned long StartEdge = 0;
+unsigned long Duration = 0;
+int SendPulseRequest = 0;
+int Triggered = 0;
+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;
+
+
+void onButtonA(MicroBitEvent evt) 
+{ 
+    if(evt.value == MICROBIT_BUTTON_EVT_CLICK)
+    {
+        SendPulseRequest = 1;
+    }
+} 
+
+void onEchoHi(MicroBitEvent evt) 
+{ 
+    StartEdge = evt.timestamp; 
+    Triggered++;
+} 
+
+void onEchoLo(MicroBitEvent evt)
+{
+    Duration = evt.timestamp - StartEdge;
+    Triggered++;
+}
+
+void onEchoPulse(MicroBitEvent evt)
+{
+    Duration = evt.timestamp;
+    Triggered++;
+}
+
+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 MoveForward(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;
+    }
+    
+    //Set the direction of the motors to forward
+    MotorDirection_L.setDigitalValue(0);
+    MotorDirection_R.setDigitalValue(0);
+    //Set the voltage of the motors as per the user request 
+    MotorSpeed_L.setAnalogValue(Voltage);  
+    MotorSpeed_R.setAnalogValue(Voltage); 
+    
+    //Store the command being used in case the command has to be paused and resumed later
+    LastMotorVoltage_L = Voltage;
+    LastMotorVoltage_R = Voltage;
+    LastMotorDirection_L = 0;
+    LastMotorDirection_R = 0;
+    //Start the timer
+    TimerStart = uBit.systemTime();
+    
+    //Update the buggy state to show that it is now running
+    BuggyState = BUGGY_RUNNING;
+}
+
+void MoveBackward(unsigned int Voltage, unsigned int Time_ms)
+{
+    int ReverseVoltage;
+    //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;
+    }
+    
+    //In reverse, 0 is actually max speed and 1024 is stopped.
+    ReverseVoltage = 1024 - Voltage;
+    
+    //Set the direction of the motors to reverse
+    MotorDirection_L.setDigitalValue(1);
+    MotorDirection_R.setDigitalValue(1);
+    //Set the voltage of the motors as per the user request (1024 - value) 
+    MotorSpeed_L.setAnalogValue(ReverseVoltage);  
+    MotorSpeed_R.setAnalogValue(ReverseVoltage); 
+    
+    //Store the command being used in case the command has to be paused and resumed later
+    LastMotorVoltage_L = ReverseVoltage;
+    LastMotorVoltage_R = ReverseVoltage;
+    LastMotorDirection_L = 1;
+    LastMotorDirection_R = 1;
+    //Start the timer
+    TimerStart = uBit.systemTime();
+    
+    //Update the buggy state to show that it is now running
+    BuggyState = BUGGY_RUNNING;
+}
+void RotateClockwise(unsigned int Voltage, unsigned int Time_ms)
+{
+    int ReverseVoltage;
+    //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;
+    }
+    
+    //In reverse, 0 is actually max speed and 1024 is stopped.
+    ReverseVoltage = 1024 - Voltage;
+    
+    //Set the motor direction: left-forward, right-backward
+    MotorDirection_L.setDigitalValue(0);
+    MotorDirection_R.setDigitalValue(1);
+    //Set the voltage of the motors as per the user request (1024 - value) 
+    MotorSpeed_L.setAnalogValue(Voltage);  
+    MotorSpeed_R.setAnalogValue(ReverseVoltage); 
+    
+    //Store the command being used in case the command has to be paused and resumed later
+    LastMotorVoltage_L = Voltage;
+    LastMotorVoltage_R = ReverseVoltage;
+    LastMotorDirection_L = 0;
+    LastMotorDirection_R = 1;
+    //Start the timer
+    TimerStart = uBit.systemTime();
+    
+    //Update the buggy state to show that it is now running
+    BuggyState = BUGGY_RUNNING;
+}
+
+void RotateAnticlockwise(unsigned int Voltage, unsigned int Time_ms)
+{
+    int ReverseVoltage;
+    //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;
+    }
+    
+    //In reverse, 0 is actually max speed and 1024 is stopped.
+    ReverseVoltage = 1024 - Voltage;
+    
+    //Set the motor direction: left-backward, right-forward
+    MotorDirection_L.setDigitalValue(1);
+    MotorDirection_R.setDigitalValue(0);
+    //Set the voltage of the motors as per the user request (1024 - value) 
+    MotorSpeed_L.setAnalogValue(ReverseVoltage);  
+    MotorSpeed_R.setAnalogValue(Voltage); 
+    
+    //Store the command being used in case the command has to be paused and resumed later
+    LastMotorVoltage_L = ReverseVoltage;
+    LastMotorVoltage_R = Voltage;
+    LastMotorDirection_L = 1;
+    LastMotorDirection_R = 0;
+    //Start the timer
+    TimerStart = uBit.systemTime();
+    
+    //Update the buggy state to show that it is now running
+    BuggyState = BUGGY_RUNNING;
+}
+
+
 int main()
 {
-    // Initialise the micro:bit runtime.
+    /*initialise local variables*/
+    unsigned long LastSystemTime = 0;   //To keep track of the clock
+    int EchoValue = 5;
+    int PressedCount = 0;
+    int ValueChange = 0;
+    
+    //Initialise the micro:bit runtime.
     uBit.init();
-
-    // Insert your code here!
-    uBit.display.scroll("HELLO WORLD! :)");
+    
+    //Display start message using the LEDs
+    uBit.display.scroll("H");
+    /*The sw MicroBitButtons instantiated above also have events assigned to them. This line will 
+    suppress MICROBIT_BUTTON_EVT_CLICK and MICROBIT_BUTTON_EVT_LONG_CLICK events on the button, otherwise
+    2 events will be flagged*/
+    buttonA.setEventConfiguration(MICROBIT_BUTTON_SIMPLE_EVENTS);
+    
+    //Listen out for the button A press event
+    uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK, onButtonA, MESSAGE_BUS_LISTENER_IMMEDIATE);
+    
+    //Set the triggerpin low
+   // Trig.setDigitalValue(0);
+    
+/*    Echo.eventOn(MICROBIT_PIN_EVENT_ON_PULSE);
+    Echo.eventOn(MICROBIT_PIN_EVENT_ON_EDGE);
+    uBit.messageBus.listen(MICROBIT_ID_IO_P13, MICROBIT_PIN_EVT_RISE, onEchoHi, MESSAGE_BUS_LISTENER_IMMEDIATE);
+    uBit.messageBus.listen(MICROBIT_ID_IO_P13, MICROBIT_PIN_EVT_FALL, onEchoLo, MESSAGE_BUS_LISTENER_IMMEDIATE);
+    uBit.messageBus.listen(MICROBIT_ID_IO_P13, MICROBIT_PIN_EVT_PULSE_HI, onEchoPulse, MESSAGE_BUS_LISTENER_IMMEDIATE);
+ */   
+     
+    /*Because this pin is being used as both input and output, the configuring of the pin as an input
+    must be done first because once the output has changed, it will not work - possible uBit bug*/
+    EchoValue = Echo.getDigitalValue();
+    uBit.display.print(EchoValue);
+    
+    while(1)
+    {
+        MoveBackward(900, 5000);
+        do
+        {
+            if(buttonA.isPressed())
+            {
+                PauseLastCommand();
+            }
+            else
+            {
+                ContinueLastCommand();
+            }
+        }while( hasLastCommandCompleted() == false );
+        wait_ms(1000);
+        
+        MoveForward(900, 5000);
+        do
+        {
+            if(buttonA.isPressed())
+            {
+                PauseLastCommand();
+            }
+            else
+            {
+                ContinueLastCommand();
+            }
+        }while( hasLastCommandCompleted() == false );
+        wait_ms(1000);
+        
+        RotateClockwise(900, 5000);
+        do
+        {
+            if(buttonA.isPressed())
+            {
+                PauseLastCommand();
+            }
+            else
+            {
+                ContinueLastCommand();
+            }
+        }while( hasLastCommandCompleted() == false );
+        wait_ms(1000);
+        
+        RotateAnticlockwise(900, 5000);
+        do
+        {
+            if(buttonA.isPressed())
+            {
+                PauseLastCommand();
+            }
+            else
+            {
+                ContinueLastCommand();
+            }
+        }while( hasLastCommandCompleted() == false );
+        wait_ms(1000);
+ 
+ #ifdef   HVHVHVHV    
+        EchoValue = Echo.getDigitalValue();
+        if(EchoValue > ValueChange) 
+        {
+            ValueChange = EchoValue;    
+        }
+       /* if( (uBit.systemTime()-LastSystemTime) > 1000)
+        {    
+            //uBit.serial.printf("Duration=%d, ", Duration);
+            LastSystemTime = uBit.systemTime();
+        }*/
+        
+        if(SendPulseRequest == 1)
+        {
+            SendPulseRequest = 0;
+            Trig.setDigitalValue(1);
+            wait_us(50);
+            Trig.setDigitalValue(0);
+            //uBit.display.printAsync(++PressedCount);
+        }
+        if(ValueChange>0)
+        {
+            uBit.display.printAsync(ValueChange);
+        }
+#endif
+    }
 
     // If main exits, there may still be other fibers running or registered event handlers etc.
     // Simply release this fiber, which will mean we enter the scheduler. Worse case, we then