Robot sy'n Gyrru ei Hun

English

Rhaglennu Robot sy'n Gyrru ei Hun

Mae'r gyfres fer hon yn arwain dysgwyr trwy fideos ac ymarferion ar raglennu cerbyd robot, yn yr achos hwn, an Car Robot Clyfar Elegoo.

Mae'r gyfres fach hon yn dilyn ymlaen o'n cyfres Electroneg a Chyflwyniad i Arduino C.

Dewiswch bennawd sesiwn i ddechrau arni.

Gwers Fideo

Adnoddau Tinkercad

I gael atgoffa o sut i fewngofnodi a defnyddio Tinkercad, gweler Sesiwn Un o'n Cyfres Electroneg Ar-lein

Rydym wedi dylunio a darparu efelychiad Tinkercad o electroneg y car robot ar gyfer yr ymarferion hyn.

Dewiswch yr opsiwn "Tinker This" i gadw'r dyluniad yn eich cyfrif i'w olygu.

Mae yna rai newidiadau i'r cynllun ar gyfer y gylched hon. Dim ond dau fodur sydd gan yr efelychiad gan fod olwynion y robot mewn parau, ac mae'r synwyryddion sy'n dilyn y llinell wedi eu disodli gan Synwyryddion Is-goch Goddefol (SIG) sydd wedi'u rhaglennu yn yr un ffordd.

Ymarferion

Mae'r heriau hyn yn golygu dechrau ar raglennu ein Car Robot Clyfar Elegoo.

Dylai pob dysgwr ddechrau gyda'r lefel efydd a gweithio eu ffordd i fyny cyn belled ag y gallent.

Cliciwch ar bennawd pob her i'w ehangu.


Mae'r atebion ar gyfer pob cam yn dangos dim ond y rhan o'r cod sydd wedi'i newid. Gellir gweld y rhaglen lawn ar ddiwedd yr adran hon.

  1. Dilëwch gynnwys y void setup() a'r void loop().


    • Cadwch y swyddogaethau setup a loop yn barod ar gyfer cynnwys newydd.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.

    Dylai eich rhaglen edrych fel hyn:

                        
      //C++ code
      //
      
      void setup()
      {
    
      }
    
      void loop()
      {
        
      }
                        
                      

  2. Diffiniwch y cysonion canlynol: leftDrivePin ar bin 5, rightDrivePin ar bin 6, leftForwardPin ar bin 7, leftReversePin ar bin 8, rightForwardPin ar bin 11, a rightReversePin ar bin 9.


    • Dylid creu cysonion a newidynnau drwy'r cyfan cyn unrhyw swyddogaethau.

    • Defnyddiwch y strwythur isod i ddiffinio cysonyn:
                            
        #define constantName value
                            
                          

    • Nid oes gan y llinellau hyn hanner colon (;) ar y diwedd.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      //C++ code
      //
    
      #define leftDrivePin 5
      #define rightDrivePin 6
      #define leftForwardPin 7
      #define leftReversePin 8
      #define rightForwardPin 11
      #define rightReversePin 9
    
      void setup() 
                        
                      

  3. Yn y void setup() bydd angen i chi osod pinMode ar gyfer pob un o'r cysonion hyn.


    • Dylid gosod y rhain i gyd i 'OUTPUT'.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      void setup()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(leftDrivePin, OUTPUT);
        pinMode(rightDrivePin, OUTPUT);
      }
                        
                      

  4. Crëwch newidyn math cyfanrif newydd o'r enw carSpeed. Gellir gosod hwn i unrhyw werth rhwng 0 (stop) a 255 (cyflymder llawn).


    • Dylid creu cysonion a newidynnau drwy'r cyfan cyn unrhyw swyddogaethau.

    • Cofiwch, mae Arduino C yn defnyddio 'int' ar gyfer newidyn cyfanrif. Mae'r math hwn o newidyn yn storio rhif cyfan.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      #define rightForwardPin 11
    
      int carSpeed = 200;
    
      void setup()
                        
                      

  5. Crëwch bum swyddogaeth newydd o'r enw: robotForward (), robotReverse(), robotLeft (), robotRight (), a robotStop ().


    • Byddwn yn defnyddio'r swyddogaethau hyn yn y void loop(), felly'r arfer gorau fyddai ysgrifennu'r rhain uwch ei ben yn y rhaglen.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      int carSpeed = 200;
    
      void robotForward()
      {
    
      }
    
      void robotReverse()
      {
    
      }
    
      void robotLeft()
      {
    
      }
    
      void robotRight()
      {
    
      }
    
      void robotStop()
      {
    
      }
    
      void setup()
                        
                      

  6. Gan ddefnyddio'r enghraifft isod ar gyfer robotForward() fel templed, cwblhewch y swyddogaethau newydd hyn.

                    
      void robotForward(){
    
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Forward");
    
      }
                    
                  

    Awgrym: Bydd angen i chi gychwyn y monitor cyfresol yn y void setup() wrth i ni argraffu iddo.


    • Cofiwch, i droelli i'r dde, bydd angen i'r olwynion chwith fynd ymlaen tra bod yr olwynion dde yn mynd yn ôl. Mae'r gwrthwyneb yn wir er mwyn troelli i'r chwith.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      void robotForward()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Forward");
      }
    
      void robotReverse()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Reverse");
      }
    
      void robotLeft()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Spin Left");
      }
    
      void robotRight()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Spin Right");
      }
    
      void robotStop()
      {
        analogWrite(leftDrivePin, 0);
        analogWrite(rightDrivePin, 0);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Stop!");
      }
    
      void setup()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(leftDrivePin, OUTPUT);
        pinMode(rightDrivePin, OUTPUT);
        Serial.begin(9600);
      }
                        
                      

  7. Yn y void loop(), crëwch raglen sy'n gwneud i'r robot deithio ymlaen am 2 eiliad, troi i'r chwith am 1 eiliad, stopio am 3 eiliad, bagio am 5 eiliad, troi i'r dde am 4 eiliad, ymlaen am 3 eiliad, ac yna stopio.


    • I alw swyddogaeth, defnyddiwch enw'r swyddogaeth gyda chromfachau a gorffennwch y llinell gyda hanner colon (;).

    • Er enghraifft, i alw'r swyddogaeth gyrru ymlaen:
                            
        void loop()
        {
          robotForward();
        }
                            
                          

    • Defnyddiwch y gorchymyn delay() i aros. Cofiwch, mae'r gwerth i mewn y cromfachau hyn yn cael ei fesur mewn milieiliadau. Felly, bydd delay(1000) yn aros am un eiliad cyn symud i'r cyfarwyddyd nesaf.

    • Mae'r rhaglen hon yn y void loop() a fydd yn parhau i ailadrodd y gyfres o symudiadau.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      void loop()
      {
        robotForward();
        delay(2000);
        robotLeft();
        delay(1000);
        robotStop();
        delay(3000);
        robotReverse();
        delay(5000);
        robotRight();
        delay (4000);
        robotForward();
        delay(3000);
        robotStop();
      }
                        
                      



                          
      //C++ code
      //
    
      #define leftDrivePin 5
      #define rightDrivePin 6
      #define leftForwardPin 7
      #define leftReversePin 8
      #define rightForwardPin 11
      #define rightReversePin 9 
      
      int carSpeed = 200;
    
      void robotForward()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Forward");
      }
    
      void robotReverse()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Reverse");
      }
    
      void robotLeft()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Spin Left");
      }
    
      void robotRight()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Spin Right");
      }
    
      void robotStop()
      {
        analogWrite(leftDrivePin, 0);
        analogWrite(rightDrivePin, 0);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Stop!");
      }
    
      void setup()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(leftDrivePin, OUTPUT);
        pinMode(rightDrivePin, OUTPUT);
        Serial.begin(9600);
      }
    
      void loop()
      {
        robotForward();
        delay(2000);
        robotLeft();
        delay(1000);
        robotStop();
        delay(3000);
        robotReverse();
        delay(5000);
        robotRight();
        delay (4000);
        robotForward();
        delay(3000);
        robotStop();
      }
                          
                        



Mae'r ymarferion hyn yn parhau i adeiladu ar yr un rhaglen.

Mae'r atebion ar gyfer pob cam yn dangos dim ond y rhan o'r cod sydd wedi'i newid. Gellir gweld y rhaglen lawn ar ddiwedd yr adran hon.

  1. Crëwch newidynnau math cyfanrif newydd o'r enw Echo a Trig. Gosodwch y rhain i'r gwerthoedd pin y maent yn cysylltu â nhw ar yr Arduino.


    • Caiff y rhain eu gosod yn yr un ffordd ac yn yr un rhan o'r rhaglen â'r newidyn carSpeed yn yr ymarferion Lefel Efydd.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      int carSpeed = 200;
      int Echo = A4;
      int Trig = A5;
    
      void robotForward()
                        
                      

  2. Crewch pinModes yn y void setup() ar gyfer y rhain.


    • Mae'r Echo yn fewnbwn, ac mae'r sbardun yn allbwn.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      void setup()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(leftDrivePin, OUTPUT);
        pinMode(rightDrivePin, OUTPUT);
        Serial.begin(9600);
        pinMode(Echo, INPUT);    
        pinMode(Trig, OUTPUT); 
      }
                        
                      

  3. I ddefnyddio'r synhwyrydd uwchsain, mae angen swyddogaeth arbennig a fydd yn creu gwerth math cyfanrif ar gyfer y pellter a fesurir. Ychwanegwch y swyddogaeth isod i'ch rhaglen:
                    
      int Distance_test(){
    
        digitalWrite(Trig, LOW);
        delayMicroseconds(2);
        digitalWrite(Trig, HIGH);
        delayMicroseconds(10);
        digitalWrite(Trig, LOW);
        float distance = pulseIn(Echo, HIGH);
        distance = distance / 2 / 29;
        return (int)distance;
    
      }
                    
                  

    • Rhowch y swyddogaeth hon cyn y ddolen void loop() yn eich rhaglen.

    • Gwnewch yn siŵr eich bod wedi defnyddio yr un enwau yn union ar gyfer y newidynnau ag a roddir yng ngham un, neu fydd y swyddogaeth ddim yn rhedeg.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      
      int Distance_test()
      {
        digitalWrite(Trig, LOW);
        delayMicroseconds(2);
        digitalWrite(Trig, HIGH);
        delayMicroseconds(10);
        digitalWrite(Trig, LOW);
        float distance = pulseIn(Echo, HIGH);
        distance = distance / 2 / 29;
        return (int)distance;
      }
      
      void setup()
    
                        
                      

  4. Yn eich void loop(), galwch y swyddogaeth newydd hon ac argraffwch y gwerth ar y monitor cyfresol. Hefyd, argraffwch "cm" ar ddiwedd y gwerth hwn yn y monitor cyfresol.


    • Gallwch alw'r swyddogaeth Distance_test() y tu mewn i gromfachau Serial.print().

    • Bydd angen ail orchymyn serial print ar gyfer llinyn "cm".

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      void loop()
      {
        robotForward();
        delay(2000);
        robotLeft();
        delay(1000);
        robotStop();
        delay(3000);
        robotReverse();
        delay(5000);
        robotRight();
        delay (4000);
        robotForward();
        delay(3000);
        robotStop();
        Serial.print(Distance_test());
        Serial.println("cm");
      }
                        
                      



                          
      //C++ code
      //
    
      #define leftDrivePin 5
      #define rightDrivePin 6
      #define leftForwardPin 7
      #define leftReversePin 8
      #define rightForwardPin 11
      #define rightReversePin 9 
      
      int carSpeed = 200;
      int Echo = A4;
      int Trig = A5;
    
      void robotForward()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Forward");
      }
    
      void robotReverse()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Reverse");
      }
    
      void robotLeft()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Spin Left");
      }
    
      void robotRight()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Spin Right");
      }
    
      void robotStop()
      {
        analogWrite(leftDrivePin, 0);
        analogWrite(rightDrivePin, 0);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Stop!");
      }
    
      int Distance_test()
      {
        digitalWrite(Trig, LOW);
        delayMicroseconds(2);
        digitalWrite(Trig, HIGH);
        delayMicroseconds(10);
        digitalWrite(Trig, LOW);
        float distance = pulseIn(Echo, HIGH);
        distance = distance / 2 / 29;
        return (int)distance;
      }
    
      void setup()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(leftDrivePin, OUTPUT);
        pinMode(rightDrivePin, OUTPUT);
        Serial.begin(9600);
        pinMode(Echo, INPUT);    
        pinMode(Trig, OUTPUT); 
      }
    
      void loop()
      {
        robotForward();
        delay(2000);
        robotLeft();
        delay(1000);
        robotStop();
        delay(3000);
        robotReverse();
        delay(5000);
        robotRight();
        delay (4000);
        robotForward();
        delay(3000);
        robotStop();
        Serial.print(Distance_test());
        Serial.println("cm");
      }
                          
                        



Mae'r ymarferion hyn yn parhau i adeiladu ar yr un rhaglen.

Mae'r atebion ar gyfer pob cam yn dangos dim ond y rhan o'r cod sydd wedi'i newid. Gellir gweld y rhaglen lawn ar ddiwedd yr adran hon.

  1. Ychwanegwch y llyfrgell servo at eich rhaglen ac enwi eich servo yn myServo.


    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      //C++ code
      //
    
      #include <Servo.h>
      Servo myServo;  //creates a servo which can be called by name
    
      #define leftDrivePin 5 
                        
                      

  2. Diffiniwch gysonyn newydd o'r enw servoPin a'i osod i'r gwerth pin y mae'r servo yn cysylltu iddo ar yr Arduino.


    • Gellir ychwanegu hwn at y rhestr o gysonion eraill a ddiffinnir yn eich rhaglen.

    • Cofiwch, peidiwch ag ychwanegu hanner colon ar ddiwedd y datganiad #define.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      #define rightReversePin 9
      #define servoPin 3
      
      int carSpeed = 200;
                        
                      

  3. Bydd angen i chi osod pa bin y mae'r servo wedi ei gysylltu iddo yn y void setup().


    • Mae'r gorchymyn yn defnyddio'r templed canlynol:
                            
        servoName.attach(pinName);
                            
                          

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      void setup()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(leftDrivePin, OUTPUT);
        pinMode(rightDrivePin, OUTPUT);
        Serial.begin(9600);
        pinMode(Echo, INPUT);    
        pinMode(Trig, OUTPUT);
        myServo.attach(servoPin);
      }
                        
                      

  4. Crëwch dri newidyn math cyfanrif newydd o'r enw rightDistance, middleDistance, a leftDistance. Gosodwch bob un i 0.


    • Mae'r rhain i gyd yn newidynnau drwy'r cyfan.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      int Trig = A5;
      int rightDistance = 0;
      int middleDistance = 0;
      int leftDistance = 0;
    
      void robotForward()
                        
                      

  5. Y tu mewn i'ch void loop(), ysgrifennwch raglen a fydd yn symud y servo i 0°, yn cymryd darlleniad uwchsain, ac yna'n ei storio yn y newidyn leftDistance. Defnyddiwch hwn i ddisodli'r llinellau a ychwanegwyd yn ymarfer pedwar y Lefel Arian.


    • Galwch swyddogaeth myServo.write() (o'r llyfrgell servo) gyda gwerth yr ongl yn y cromfachau.

    • Cofiwch, ychwanegu oediad (500 milieiliad) i roi amser i'r servo gwblhau'r symudiad cyn cymryd darlleniad.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      void loop()
      {
        robotForward();
        delay(2000);
        robotLeft();
        delay(1000);
        robotStop();
        delay(3000);
        robotReverse();
        delay(5000);
        robotRight();
        delay (4000);
        robotForward();
        delay(3000);
        robotStop();
        myServo.write(0);
        delay(500);
        leftDistance = Distance_test();
        Serial.print(leftDistance);
        Serial.println("cm on left");
      }
                        
                      

  6. Ailadroddwch hyn i symud y servo i 90° ar gyfer y pellter canol (middleDistance), a 180° ar gyfer y pellter i'r dde (rightDistance).


                      
      void loop()
      {
        robotForward();
        delay(2000);
        robotLeft();
        delay(1000);
        robotStop();
        delay(3000);
        robotReverse();
        delay(5000);
        robotRight();
        delay (4000);
        robotForward();
        delay(3000);
        robotStop();
        myServo.write(0);
        delay(500);
        leftDistance = Distance_test();
        Serial.print(leftDistance);
        Serial.println("cm on left");
        myServo.write(90);
        delay(500);
        middleDistance = Distance_test();
        Serial.print(middleDistance);
        Serial.println("cm ahead");
        myServo.write(180);
        delay(500);
        rightDistance = Distance_test();
        Serial.print(rightDistance);
        Serial.println("cm on right");
      }
                      
                    

  7. Gan ddefnyddio os-ddatganiadau, canfyddwch pa gyfeiriad sydd â'r rhwystr agosaf, a pha un sydd â'r llwybr mwyaf clir. Argraffwch yr atebion yn y monitor cyfresol.


    • Bydd angen i chi feddwl sut i gymharu'r gwerthoedd i ganfod yr uchaf a'r isaf.

    • Cofiwch, gallwch bentyrru os ac arall ddatganiadau o fewn ei gilydd.

    • Gallwch ddefnyddio gweithredwr "and" Boole ar gyfer yr ymarfer hwn. Mae hyn yn ein galluogi i wirio yn erbyn dau opsiwn. Mae Arduino C yn defnyddio && yn lle'r gair "and" fel y dangosir isod:

                            
        if (rightDistance > middleDistance && rightDistance > leftDistance)
        {
          Serial.print("Right is the safest Direction");
        }
                            
                          

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      if (rightDistance > middleDistance && rightDistance > leftDistance)
      {
        Serial.print("Right is the safest direction");
        if (middleDistance < leftDistance)
        {
          Serial.print("Do not go forwards");
        }
        else
        {
          Serial.print("Do not go left");
        }
      } 
      else if (leftDistance > middleDistance)
      {
        Serial.print("Left is the safest direction");
        if (middleDistance < rightDistance)
        {
          Serial.print("Do not go forwards");
        }
        else
        {
          Serial.print("Do not go right");
        }
      }
      else
      {
        Serial.print("Forwards is the safest direction");
        if (leftDistance < rightDistance)
        {
          Serial.print("Do not go left");
        }
        else
        {
          Serial.print("Do not go right");
        }
      }
                        
                      



                          
      //C++ code
      //
    
      #include <Servo.h>
      Servo myServo;  //creates a servo which can be called by name
    
      #define leftDrivePin 5
      #define rightDrivePin 6
      #define leftForwardPin 7
      #define leftReversePin 8
      #define rightForwardPin 11
      #define rightReversePin 9 
      #define servoPin 3
      
      int carSpeed = 200;
      int Echo = A4;
      int Trig = A5;
      int rightDistance = 0;
      int middleDistance = 0;
      int leftDistance = 0;
    
      void robotForward()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Forward");
      }
    
      void robotReverse()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Reverse");
      }
    
      void robotLeft()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Spin Left");
      }
    
      void robotRight()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Spin Right");
      }
    
      void robotStop()
      {
        analogWrite(leftDrivePin, 0);
        analogWrite(rightDrivePin, 0);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Stop!");
      }
    
      int Distance_test()
      {
        digitalWrite(Trig, LOW);
        delayMicroseconds(2);
        digitalWrite(Trig, HIGH);
        delayMicroseconds(10);
        digitalWrite(Trig, LOW);
        float distance = pulseIn(Echo, HIGH);
        distance = distance / 2 / 29;
        return (int)distance;
      }
    
      void setup()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(leftDrivePin, OUTPUT);
        pinMode(rightDrivePin, OUTPUT);
        Serial.begin(9600);
        pinMode(Echo, INPUT);    
        pinMode(Trig, OUTPUT);
        myServo.attach(servoPin);
      }
    
      void loop()
      {
        robotForward();
        delay(2000);
        robotLeft();
        delay(1000);
        robotStop();
        delay(3000);
        robotReverse();
        delay(5000);
        robotRight();
        delay (4000);
        robotForward();
        delay(3000);
        robotStop();
        myServo.write(0);
        delay(500);
        leftDistance = Distance_test();
        Serial.print(leftDistance);
        Serial.println("cm on left");
        myServo.write(90);
        delay(500);
        middleDistance = Distance_test();
        Serial.print(middleDistance);
        Serial.println("cm ahead");
        myServo.write(180);
        delay(500);
        rightDistance = Distance_test();
        Serial.print(rightDistance);
        Serial.println("cm on right");
        if (rightDistance > middleDistance && rightDistance > leftDistance)
        {
          Serial.print("Right is the safest direction");
          if (middleDistance < leftDistance)
          {
            Serial.print("Do not go forwards");
          }
          else
          {
            Serial.print("Do not go left");
          }
        } 
        else if (leftDistance > middleDistance)
        {
          Serial.print("Left is the safest direction");
          if (middleDistance < rightDistance)
          {
            Serial.print("Do not go forwards");
          }
          else
          {
            Serial.print("Do not go right");
          }
        }
        else
        {
          Serial.print("Forwards is the safest direction");
          if (leftDistance < rightDistance)
          {
            Serial.print("Do not go left");
          }
          else
          {
            Serial.print("Do not go right");
          }
        }
      }
                          
                        


Os nad ydych chi wedi gwneud hynny'n barod, tynnwch y rhaglen symud y tu mewn i'r void loop() o'r ymarferion Lefel Efydd. Yna, rhowch gynnig ar ysgrifennu rhaglen sy'n peri i'r robot yrru ei hun ar hyd y llwybr mwyaf clir. Cofiwch, mae troi yn golygu troelli yn y fan, felly bydd angen i chi ganfod pa bryd i roi'r gorau i droi er mwyn parhau i symud ymlaen yn ddiogel.


Video Lesson

Exercises

We shall be continuing with your program from last session.

Make sure you've finished Session One (up to and including Gold) before starting these.

These challenges involve programming our Elegoo Smart Robot Car to follow a line.

All learners should start with the bronze level and work their way up as far as they can.

Click on each challenge heading to expand.


The Elegoo Smart Robot Car has three line follow sensors - these are not available on Tinkercad. Instead, we have used three PIR sensors which work with the same programming.

  1. Define global constants for the three PIR sensor pins.


    • Add these in the same section as the others from last session.

    • Possible names could be leftPIRPin, middlePIRPin, and rightPIRPin.

    • Look at the circuit to determine which pins they connect to.

    • Remember, when defining constants there is no semi-colon (;).

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      #define leftDrivePin 5
      #define rightDrivePin 6
      #define leftForwardPin 7
      #define leftReversePin 8
      #define rightForwardPin 11
      #define rightReversePin 9 
      #define servoPin 3
      #define leftPIRPin 2
      #define middlePIRPin 4
      #define rightPIRPin 10
                        
                      

  2. Set the pinModes for each of these sensors.


    • These are done in the void setup() function in the same format as the others.

    • PIR sensors are digital input devices.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      void setup()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(leftDrivePin, OUTPUT);
        pinMode(rightDrivePin, OUTPUT);
        Serial.begin(9600);
        pinMode(Echo, INPUT);    
        pinMode(Trig, OUTPUT);
        myServo.attach(servoPin);
        pinMode(leftPIRPin, INPUT);
        pinMode(middlePIRPin, INPUT);
        pinMode(rightPIRPin, INPUT);
      }
                        
                      

  3. Create new functions to move the contents of the void loop() from last session to.


    • Consider a function for the movement program (Session One Bronze), and one for the ultrasonic obstacle detection and movement.

    • This will keep the code ready for calling if needed for later exercises.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.

    This is just one way you could split up the functions.

                        
      void setPath()
      {
        robotForward();
        delay(2000);
        robotLeft();
        delay(1000);
        robotStop();
        delay(3000);
        robotReverse();
        delay(5000);
        robotRight();
        delay (4000);
        robotForward();
        delay(3000);
        robotStop();
        myServo.write(0);
        delay(500);
      }
    
      void ultrasonicCheck()
      {
        leftDistance = Distance_test();
        Serial.print(leftDistance);
        Serial.println("cm on left");
        myServo.write(90);
        delay(500);
        middleDistance = Distance_test();
        Serial.print(middleDistance);
        Serial.println("cm ahead");
        myServo.write(180);
        delay(500);
        rightDistance = Distance_test();
        Serial.print(rightDistance);
        Serial.println("cm on right");
        if (rightDistance > middleDistance && rightDistance > leftDistance)
        {
          Serial.print("Right is the safest direction");
          if (middleDistance < leftDistance)
          {
            Serial.print("Do not go forwards");
          }
          else
          {
            Serial.print("Do not go left");
          }
        } 
        else if (leftDistance > middleDistance)
        {
          Serial.print("Left is the safest direction");
          if (middleDistance < rightDistance)
          {
            Serial.print("Do not go forwards");
          }
          else
          {
            Serial.print("Do not go right");
          }
        }
        else
        {
          Serial.print("Forwards is the safest direction");
          if (leftDistance < rightDistance)
          {
            Serial.print("Do not go left");
          }
          else
          {
            Serial.print("Do not go right");
          }
        }
      }
    
      void loop()
      {
        
      }
                        
                      

  4. Add a new function called lineFollow() and call it in the void loop().


                      
      void lineFollow()
      {
    
      }
    
      void loop ()
      {
        lineFollow();
      }
                      
                    



                        
      //C++ code
      //
    
      #include <Servo.h>
      Servo myServo;  //creates a servo which can be called by name
    
      #define leftDrivePin 5
      #define rightDrivePin 6
      #define leftForwardPin 7
      #define leftReversePin 8
      #define rightForwardPin 11
      #define rightReversePin 9 
      #define servoPin 3
      #define leftPIRPin 2
      #define middlePIRPin 4
      #define rightPIRPin 10
      
      int carSpeed = 200;
      int Echo = A4;
      int Trig = A5;
      int rightDistance = 0;
      int middleDistance = 0;
      int leftDistance = 0;
    
      void robotForward()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Forward");
      }
    
      void robotReverse()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Reverse");
      }
    
      void robotLeft()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Spin Left");
      }
    
      void robotRight()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Spin Right");
      }
    
      void robotStop()
      {
        analogWrite(leftDrivePin, 0);
        analogWrite(rightDrivePin, 0);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Stop!");
      }
    
      int Distance_test()
      {
        digitalWrite(Trig, LOW);
        delayMicroseconds(2);
        digitalWrite(Trig, HIGH);
        delayMicroseconds(10);
        digitalWrite(Trig, LOW);
        float distance = pulseIn(Echo, HIGH);
        distance = distance / 2 / 29;
        return (int)distance;
      }
    
      void setup()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(leftDrivePin, OUTPUT);
        pinMode(rightDrivePin, OUTPUT);
        Serial.begin(9600);
        pinMode(Echo, INPUT);    
        pinMode(Trig, OUTPUT);
        myServo.attach(servoPin);
        pinMode(leftPIRPin, INPUT);
        pinMode(middlePIRPin, INPUT);
        pinMode(rightPIRPin, INPUT);
      }
    
      void setPath()
      {
        robotForward();
        delay(2000);
        robotLeft();
        delay(1000);
        robotStop();
        delay(3000);
        robotReverse();
        delay(5000);
        robotRight();
        delay (4000);
        robotForward();
        delay(3000);
        robotStop();
        myServo.write(0);
        delay(500);
      }
    
      void ultrasonicCheck()
      {
        leftDistance = Distance_test();
        Serial.print(leftDistance);
        Serial.println("cm on left");
        myServo.write(90);
        delay(500);
        middleDistance = Distance_test();
        Serial.print(middleDistance);
        Serial.println("cm ahead");
        myServo.write(180);
        delay(500);
        rightDistance = Distance_test();
        Serial.print(rightDistance);
        Serial.println("cm on right");
        if (rightDistance > middleDistance && rightDistance > leftDistance)
        {
          Serial.print("Right is the safest direction");
          if (middleDistance < leftDistance)
          {
            Serial.print("Do not go forwards");
          }
          else
          {
            Serial.print("Do not go left");
          }
        } 
        else if (leftDistance > middleDistance)
        {
          Serial.print("Left is the safest direction");
          if (middleDistance < rightDistance)
          {
            Serial.print("Do not go forwards");
          }
          else
          {
            Serial.print("Do not go right");
          }
        }
        else
        {
          Serial.print("Forwards is the safest direction");
          if (leftDistance < rightDistance)
          {
            Serial.print("Do not go left");
          }
          else
          {
            Serial.print("Do not go right");
          }
        }
      }
    
      void lineFollow()
      {
    
      }
    
      void loop ()
      {
        lineFollow();
      }
        
                        
                      




  1. Create three local Boolean type variables, one for each PIR, inside the line following function.


    • These are local variable besides we are creating them inside a function. This means they can only be used in the same function.

    • Remember, Boolean variables are either true (1), or false (0).

    • You can create a Boolean type variable without needing to set it to something immediately. Here is an example for how to create one:

                            
        bool variableName;
                            
                          

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      void lineFollow()
      {
        bool leftLine;
        bool midLine;
        bool rightLine;
      }
                        
                      

  2. Now, set each of these new variables to the digital reading of the corresponding sensor's pin.


    • Here is an example of how to assign a digital reading to a variable:
                            
        variableName = digitalRead(pinName);
                            
                          

    • As these are local variables, we need to do this in the same function they were created in.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      void lineFollow()
      {
        bool leftLine;
        bool midLine;
        bool rightLine;
        leftLine = digitalRead(leftPIRPin);
        midLine = digitalRead(middlePIRPin);
        rightLine = digitalRead(rightPIRPin);
      }
                        
                      

  3. Print the values from these line sensors to the serial monitor.


    • We have already initiated the serial monitor last session.

    • You will need two print statements, so you know which sensor reading is which in the monitor. One for a label, the other for the value.

    • For example:
                            
        Serial.print("First Sensor: ");
        Serial.println(variableName);
                            
                          

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      void lineFollow()
      {
        bool leftLine;
        bool midLine;
        bool rightLine;
        leftLine = digitalRead(leftPIRPin);
        midLine = digitalRead(middlePIRPin);
        rightLine = digitalRead(rightPIRPin);
        Serial.print("Left PIR: ");
        Serial.println(leftLine);
        Serial.print("Middle PIR: ");
        Serial.println(midLine);
        Serial.print("Right PIR: ");
        Serial.println(rightLine);
      }
                        
                      

  4. Create an if-statement inside your line follow function checking if the left reading is true whilst both the middle and right readings are negative.


    • Remember, if(booleanVariable) is checking if the value of the Boolean variable is true (1). Whilst if(!booleanVariable) is checking to see if it is false.

    • In Arduino C programming we use && for and inside a comparison.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      void lineFollow()
      {
        bool leftLine;
        bool midLine;
        bool rightLine;
        leftLine = digitalRead(leftPIRPin);
        midLine = digitalRead(middlePIRPin);
        rightLine = digitalRead(rightPIRPin);
        Serial.print("Left PIR: ");
        Serial.println(leftLine);
        Serial.print("Middle PIR: ");
        Serial.println(midLine);
        Serial.print("Right PIR: ");
        Serial.println(rightLine);
        if(leftLine && !midLine && !rightLine)
        {
    
        }
      }
                        
                      

  5. Add an else-if statement for if the middle reading is true, whilst the other readings are false.


                      
      void lineFollow()
      {
        bool leftLine;
        bool midLine;
        bool rightLine;
        leftLine = digitalRead(leftPIRPin);
        midLine = digitalRead(middlePIRPin);
        rightLine = digitalRead(rightPIRPin);
        Serial.print("Left PIR: ");
        Serial.println(leftLine);
        Serial.print("Middle PIR: ");
        Serial.println(midLine);
        Serial.print("Right PIR: ");
        Serial.println(rightLine);
        if(leftLine && !midLine && !rightLine)
        {
          
        }
        else if(!leftLine && midLine && !rightLine)
        {
    
        }
      }
                      
                    

  6. Do the same again for when the right sensor is positive whilst the other two are negative.


                      
      void lineFollow()
      {
        bool leftLine;
        bool midLine;
        bool rightLine;
        leftLine = digitalRead(leftPIRPin);
        midLine = digitalRead(middlePIRPin);
        rightLine = digitalRead(rightPIRPin);
        Serial.print("Left PIR: ");
        Serial.println(leftLine);
        Serial.print("Middle PIR: ");
        Serial.println(midLine);
        Serial.print("Right PIR: ");
        Serial.println(rightLine);
        if(leftLine && !midLine && !rightLine)
        {
          
        }
        else if(!leftLine && midLine && !rightLine)
        {
          
        }
        else if(!leftLine && !midLine && rightLine)
        {
    
        }
      }
                      
                    

  7. Inside each of these if and else-if statements, call the appropriate movement functions to keep the robot following the line.


    • We want to try and keep the line visible on the middle sensor.

    • You will need to add a delay and stop to the movement to check if you've moved enough or too far.

    • For this exercise, turn for 100ms before checking the sensors again.

    • We already created movement functions last session which we can call for this.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      if(leftLine && !midLine && !rightLine)
      {
        robotLeft();
        delay(100);
        robotStop();
      }
      else if(!leftLine && midLine && !rightLine)
      {
        robotForward();
        delay(100);
        robotStop();
      }
      else if(!leftLine && !midLine && rightLine)
      {
        robotRight();
        delay(100);
        robotStop();
      }                   
                        
                      



                          
      //C++ code
      //
    
      #include <Servo.h>
      Servo myServo;  //creates a servo which can be called by name
    
      #define leftDrivePin 5
      #define rightDrivePin 6
      #define leftForwardPin 7
      #define leftReversePin 8
      #define rightForwardPin 11
      #define rightReversePin 9 
      #define servoPin 3
      #define leftPIRPin 2
      #define middlePIRPin 4
      #define rightPIRPin 10
      
      int carSpeed = 200;
      int Echo = A4;
      int Trig = A5;
      int rightDistance = 0;
      int middleDistance = 0;
      int leftDistance = 0;
    
      void robotForward()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Forward");
      }
    
      void robotReverse()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Reverse");
      }
    
      void robotLeft()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Spin Left");
      }
    
      void robotRight()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Spin Right");
      }
    
      void robotStop()
      {
        analogWrite(leftDrivePin, 0);
        analogWrite(rightDrivePin, 0);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Stop!");
      }
    
      int Distance_test()
      {
        digitalWrite(Trig, LOW);
        delayMicroseconds(2);
        digitalWrite(Trig, HIGH);
        delayMicroseconds(10);
        digitalWrite(Trig, LOW);
        float distance = pulseIn(Echo, HIGH);
        distance = distance / 2 / 29;
        return (int)distance;
      }
    
      void setup()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(leftDrivePin, OUTPUT);
        pinMode(rightDrivePin, OUTPUT);
        Serial.begin(9600);
        pinMode(Echo, INPUT);    
        pinMode(Trig, OUTPUT);
        myServo.attach(servoPin);
        pinMode(leftPIRPin, INPUT);
        pinMode(middlePIRPin, INPUT);
        pinMode(rightPIRPin, INPUT);
      }
    
      void setPath()
      {
        robotForward();
        delay(2000);
        robotLeft();
        delay(1000);
        robotStop();
        delay(3000);
        robotReverse();
        delay(5000);
        robotRight();
        delay (4000);
        robotForward();
        delay(3000);
        robotStop();
        myServo.write(0);
        delay(500);
      }
    
      void ultrasonicCheck()
      {
        leftDistance = Distance_test();
        Serial.print(leftDistance);
        Serial.println("cm on left");
        myServo.write(90);
        delay(500);
        middleDistance = Distance_test();
        Serial.print(middleDistance);
        Serial.println("cm ahead");
        myServo.write(180);
        delay(500);
        rightDistance = Distance_test();
        Serial.print(rightDistance);
        Serial.println("cm on right");
        if (rightDistance > middleDistance && rightDistance > leftDistance)
        {
          Serial.print("Right is the safest direction");
          if (middleDistance < leftDistance)
          {
            Serial.print("Do not go forwards");
          }
          else
          {
            Serial.print("Do not go left");
          }
        } 
        else if (leftDistance > middleDistance)
        {
          Serial.print("Left is the safest direction");
          if (middleDistance < rightDistance)
          {
            Serial.print("Do not go forwards");
          }
          else
          {
            Serial.print("Do not go right");
          }
        }
        else
        {
          Serial.print("Forwards is the safest direction");
          if (leftDistance < rightDistance)
          {
            Serial.print("Do not go left");
          }
          else
          {
            Serial.print("Do not go right");
          }
        }
      }
    
      void lineFollow()
      {
        bool leftLine;
        bool midLine;
        bool rightLine;
        leftLine = digitalRead(leftPIRPin);
        midLine = digitalRead(middlePIRPin);
        rightLine = digitalRead(rightPIRPin);
        Serial.print("Left PIR: ");
        Serial.println(leftLine);
        Serial.print("Middle PIR: ");
        Serial.println(midLine);
        Serial.print("Right PIR: ");
        Serial.println(rightLine);
        if(leftLine && !midLine && !rightLine)
        {
          robotLeft();
          delay(100);
          robotStop();
        }
        else if(!leftLine && midLine && !rightLine)
        {
          robotForward();
          delay(100);
          robotStop();
        }
        else if(!leftLine && !midLine && rightLine)
        {
          robotRight();
          delay(100);
          robotStop();
        } 
      }
    
      void loop ()
      {
        lineFollow();
      }
                          
                        




  1. At the moment, our line following function is only looking for when a single sensor is reading as true. But what if the line is visible to two of the sensors? Add new else-if statements for these conditions to move the robot appropriately.


    • If two sensors are both detecting the line, then we need a smaller adjustment than for just the left or the right.

    • Halve the turning time used in the previous if and else-if statements.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      else if(leftLine && midLine && !rightLine)
      {
        robotLeft();
        delay(50);
        robotStop();
      }
      else if(!leftLine && midLine && rightLine)
      {
        robotRight();
        delay(50);
        robotStop();
      }
                        
                      

  2. Add statements and programs for if none or all three sensors are detecting a line.


    • If none of the sensors are detecting the line, you may want to consider setting a spin direction and doubling the duration before each check to try and relocate the line.

    • All three sensors detecting the line means that either you are crossing it, it's detecting more than one section of the line, or the line is thick enought to register across all 3 sensors.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      else if (!leftLine && !midLine && !rightLine)
      {
        robotRight();
        delay(200);
        robotStop();
      }                
      else if (leftLine && midLine && rightLine)
      {
        robotForward();
        delay(100);
        robotStop();
      }
                        
                      

    Bug Alert: The above answer is correct. However, there is a bug within Tinkercad that means the comparison for all three being positive, triggers an error that stops us from running the simulator.

    Be aware the error does not point to this, but to another part of the program that is not related.

    To fix this bug, use the below version of the answer. The extra pair of brackets makes no difference to the comparison but allows Tinkercad to run the code successfully.

                          
      else if (!leftLine && !midLine && !rightLine)
      {
        robotRight();
        delay(200);
        robotStop();
      }                
      else if ((leftLine && midLine) && rightLine)
      {
        robotForward();
        delay(100);
        robotStop();
      }
                          
                        

  3. Finally, add an else statement to the end of all these comparisons to capture anything missed. Inside this include an error message which prints in the serial monitor.


    • Try to make error messages that help you detect the problem. Do not just have the message "Error" for every catch point or you will struggle to find the source of the problem.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
        else
        {
          Serial.print("Error: Unexpected PIR readings");
        }
                        
                      



                          
      //C++ code
      //
    
      #include <Servo.h>
      Servo myServo;  //creates a servo which can be called by name
    
      #define leftDrivePin 5
      #define rightDrivePin 6
      #define leftForwardPin 7
      #define leftReversePin 8
      #define rightForwardPin 11
      #define rightReversePin 9 
      #define servoPin 3
      #define leftPIRPin 2
      #define middlePIRPin 4
      #define rightPIRPin 10
      
      int carSpeed = 200;
      int Echo = A4;
      int Trig = A5;
      int rightDistance = 0;
      int middleDistance = 0;
      int leftDistance = 0;
    
      void robotForward()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Forward");
      }
    
      void robotReverse()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Reverse");
      }
    
      void robotLeft()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Spin Left");
      }
    
      void robotRight()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Spin Right");
      }
    
      void robotStop()
      {
        analogWrite(leftDrivePin, 0);
        analogWrite(rightDrivePin, 0);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Stop!");
      }
    
      int Distance_test()
      {
        digitalWrite(Trig, LOW);
        delayMicroseconds(2);
        digitalWrite(Trig, HIGH);
        delayMicroseconds(10);
        digitalWrite(Trig, LOW);
        float distance = pulseIn(Echo, HIGH);
        distance = distance / 2 / 29;
        return (int)distance;
      }
    
      void setup()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(leftDrivePin, OUTPUT);
        pinMode(rightDrivePin, OUTPUT);
        Serial.begin(9600);
        pinMode(Echo, INPUT);    
        pinMode(Trig, OUTPUT);
        myServo.attach(servoPin);
        pinMode(leftPIRPin, INPUT);
        pinMode(middlePIRPin, INPUT);
        pinMode(rightPIRPin, INPUT);
      }
    
      void setPath()
      {
        robotForward();
        delay(2000);
        robotLeft();
        delay(1000);
        robotStop();
        delay(3000);
        robotReverse();
        delay(5000);
        robotRight();
        delay (4000);
        robotForward();
        delay(3000);
        robotStop();
        myServo.write(0);
        delay(500);
      }
    
      void ultrasonicCheck()
      {
        leftDistance = Distance_test();
        Serial.print(leftDistance);
        Serial.println("cm on left");
        myServo.write(90);
        delay(500);
        middleDistance = Distance_test();
        Serial.print(middleDistance);
        Serial.println("cm ahead");
        myServo.write(180);
        delay(500);
        rightDistance = Distance_test();
        Serial.print(rightDistance);
        Serial.println("cm on right");
        if (rightDistance > middleDistance && rightDistance > leftDistance)
        {
          Serial.print("Right is the safest direction");
          if (middleDistance < leftDistance)
          {
            Serial.print("Do not go forwards");
          }
          else
          {
            Serial.print("Do not go left");
          }
        } 
        else if (leftDistance > middleDistance)
        {
          Serial.print("Left is the safest direction");
          if (middleDistance < rightDistance)
          {
            Serial.print("Do not go forwards");
          }
          else
          {
            Serial.print("Do not go right");
          }
        }
        else
        {
          Serial.print("Forwards is the safest direction");
          if (leftDistance < rightDistance)
          {
            Serial.print("Do not go left");
          }
          else
          {
            Serial.print("Do not go right");
          }
        }
      }
    
      void lineFollow()
      {
        bool leftLine;
        bool midLine;
        bool rightLine;
        leftLine = digitalRead(leftPIRPin);
        midLine = digitalRead(middlePIRPin);
        rightLine = digitalRead(rightPIRPin);
        Serial.print("Left PIR: ");
        Serial.println(leftLine);
        Serial.print("Middle PIR: ");
        Serial.println(midLine);
        Serial.print("Right PIR: ");
        Serial.println(rightLine);
        if(leftLine && !midLine && !rightLine)
        {
          robotLeft();
          delay(100);
          robotStop();
        }
        else if(!leftLine && midLine && !rightLine)
        {
          robotForward();
          delay(100);
          robotStop();
        }
        else if(!leftLine && !midLine && rightLine)
        {
          robotRight();
          delay(100);
          robotStop();
        }
        else if(leftLine && midLine && !rightLine)
        {
          robotLeft();
          delay(50);
          robotStop();
        }
        else if(!leftLine && midLine && rightLine)
        {
          robotRight();
          delay(50);
          robotStop();
        }
        else if (!leftLine && !midLine && !rightLine)
        {
          robotRight();
          delay(200);
          robotStop();
        }                
        else if (leftLine && midLine && rightLine)
        {
          robotForward();
          delay(100);
          robotStop();
        }
        else
        {
          Serial.print("Error: Unexpected PIR readings")
        }
      }
    
      void loop ()
      {
        lineFollow();
      }
                          
                        




Video Lesson

Exercises

We shall be continung with your program from last session.

Make sure you've finished Gold Level for both Session One and Two before starting these.

These challenges involve programming our Elegoo Smart Robot Car to respond to an IR remote control.

All learners should start with the bronze level and work their way up as far as they can.

Click on each challenge heading to expand.



  1. Define a constant for the IR receiver which is set to the correct pin on the Arduino.


                      
      #define irReceiverPin 12
                      
                    

  2. To use the IR remote, you will need to include its library of functions.


    • Use the #include command as we did for the servo library.

    • The IR remote library is call IRremote.hpp

    • Do not include a semi-colon at the end of a #include instruction.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      #include <IRremote.hpp>
                        
                      

  3. In your void setup(), initialise the IR receiver.


    • This function is from the IR remote library and replaces the need to set a pinMode for the receiver.

    • Use this function template:
                            
        IrReceiver.begin(pinName, ENABLE_LED_FEEDBACK);
                            
                          

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      IrReceiver.begin(irReceiverPin, ENABLE_LED_FEEDBACK);
                        
                      

  4. Inside your loop function, add an if statement to detect if a signal has been received from the remote.


    • The IR remote library includes a function called IrReceiver.decode() for checking if a signal is received.

    • This function returns TRUE if a signal is detected.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      if (IrReceiver.decode())
      {
    
      }
                        
                      

  5. Have the command received from the remote print into the serial monitor.

    Hex Values: Until now, we have been only working with the decimal counting system, using the digits 0-9. The Hex system has 16 digits in it's counting instead of 10, these are; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, and F.

    Remember, that to identify a hex value inside our Arduino C code, we need to put a '0x' before the value.


    • The necessary Serial.print() line needs to be inside the if statement for when an IR signal is received.

    • This uses another of the IR remote library's instructions - called IrReceiver.decodedIRData.command.

    • The commands are sent as HEX values which we need to include in the print instruction:
                            
        Serial.println(value, HEX);
                            
                          

    • To use HEX values, you will need to add 0x to the start of the value. For example if the command returns 18, the true value for comparisons in your program is 0x18.

    • You may wish to include some text before your value to identify it in the serial monitor, as well as to remind you that the value should start "0x" when applying it later.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      if (IrReceiver.decode())
      {
        Serial.print("IR command received: 0x");
        Serial.println(IrReceiver.decodedIRData.command, HEX);
      }
                        
                      

  6. Currently, the program listens for only the first command sent. We need to resume the IR receiver after printing its value to the serial monitor.


    • This uses another function from the IR remote library:
                            
        IrReceiver.resume();
                            
                          

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      if (IrReceiver.decode())
      {
        Serial.print("IR command received: 0x");
        Serial.println(IrReceiver.decodedIRData.command, HEX);
        IrReceiver.resume();
      }
                        
                      


                          
      //C++ code
      //
      
      #include <Servo.h>
      #include <IRremote.hpp>
      Servo myServo;  //creates a servo which can be called by name
      
      #define leftDrivePin 5
      #define rightDrivePin 6
      #define leftForwardPin 7
      #define leftReversePin 8
      #define rightForwardPin 11
      #define rightReversePin 9 
      #define servoPin 3
      #define leftPIRPin 2
      #define middlePIRPin 4
      #define rightPIRPin 10
      #define irReceiverPin 12
      
      int carSpeed = 200;
      int Echo = A4;
      int Trig = A5;
      int rightDistance = 0;
      int middleDistance = 0;
      int leftDistance = 0;
      
      void robotForward()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Forward");
      }
      
      void robotReverse()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Reverse");
      }
      
      void robotLeft()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Spin Left");
      }
      
      void robotRight()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Spin Right");
      }
      
      void robotStop()
      {
        analogWrite(leftDrivePin, 0);
        analogWrite(rightDrivePin, 0);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Stop!");
      }
      
      int Distance_test()
      {
        digitalWrite(Trig, LOW);
        delayMicroseconds(2);
        digitalWrite(Trig, HIGH);
        delayMicroseconds(10);
        digitalWrite(Trig, LOW);
        float distance = pulseIn(Echo, HIGH);
        distance = distance / 2 / 29;
        return (int)distance;
      }
      
      void setup()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(leftDrivePin, OUTPUT);
        pinMode(rightDrivePin, OUTPUT);
        Serial.begin(9600);
        pinMode(Echo, INPUT);    
        pinMode(Trig, OUTPUT);
        myServo.attach(servoPin);
        pinMode(leftPIRPin, INPUT);
        pinMode(middlePIRPin, INPUT);
        pinMode(rightPIRPin, INPUT);
        IrReceiver.begin(irReceiverPin, ENABLE_LED_FEEDBACK);
      }
      
      void setPath()
      {
        robotForward();
        delay(2000);
        robotLeft();
        delay(1000);
        robotStop();
        delay(3000);
        robotReverse();
        delay(5000);
        robotRight();
        delay (4000);
        robotForward();
        delay(3000);
        robotStop();
        myServo.write(0);
        delay(500);
      }
      
      void ultrasonicCheck()
      {
        leftDistance = Distance_test();
        Serial.print(leftDistance);
        Serial.println("cm on left");
        myServo.write(90);
        delay(500);
        middleDistance = Distance_test();
        Serial.print(middleDistance);
        Serial.println("cm ahead");
        myServo.write(180);
        delay(500);
        rightDistance = Distance_test();
        Serial.print(rightDistance);
        Serial.println("cm on right");
        if (rightDistance > middleDistance && rightDistance > leftDistance)
        {
          Serial.print("Right is the safest direction");
          if (middleDistance < leftDistance)
          {
            Serial.print("Do not go forwards");
          }
          else
          {
            Serial.print("Do not go left");
          }
        } 
        else if (leftDistance > middleDistance)
        {
          Serial.print("Left is the safest direction");
          if (middleDistance < rightDistance)
          {
            Serial.print("Do not go forwards");
          }
          else
          {
            Serial.print("Do not go right");
          }
        }
        else
        {
          Serial.print("Forwards is the safest direction");
          if (leftDistance < rightDistance)
          {
            Serial.print("Do not go left");
          }
          else
          {
            Serial.print("Do not go right");
          }
        }
      }
      
      void lineFollow()
      {
        bool leftLine;
        bool midLine;
        bool rightLine;
        leftLine = digitalRead(leftPIRPin);
        midLine = digitalRead(middlePIRPin);
        rightLine = digitalRead(rightPIRPin);
        Serial.print("Left PIR: ");
        Serial.println(leftLine);
        Serial.print("Middle PIR: ");
        Serial.println(midLine);
        Serial.print("Right PIR: ");
        Serial.println(rightLine);
        if(leftLine && !midLine && !rightLine)
        {
          robotLeft();
          delay(100);
          robotStop();
        }
        else if(!leftLine && midLine && !rightLine)
        {
          robotForward();
          delay(100);
          robotStop();
        }
        else if(!leftLine && !midLine && rightLine)
        {
          robotRight();
          delay(100);
          robotStop();
        }
        else if(leftLine && midLine && !rightLine)
        {
          robotLeft();
          delay(50);
          robotStop();
        }
        else if(!leftLine && midLine && rightLine)
        {
          robotRight();
          delay(50);
          robotStop();
        }
        else if (!leftLine && !midLine && !rightLine)
        {
          robotRight();
          delay(200);
          robotStop();
        }                
        else if (leftLine && midLine && rightLine)
        {
          robotForward();
          delay(100);
          robotStop();
        }
        else
        {
          Serial.print("Error: Unexpected PIR readings");
        }
      }
      
      void loop ()
      {
        //lineFollow(); blocked out to allow easy read of remote values in serial monitor.
        if (IrReceiver.decode())
        {
        Serial.print("IR command received: 0x");
          Serial.println(IrReceiver.decodedIRData.command, HEX);
          IrReceiver.resume();
        }
      }                      
                          
                        




  1. Using your current program, identify which commands are sent by each button on the controller.

    Here are the HEX values for some of the buttons on the IR remote:

    • Button 5 = 0x15
    • VOL+ = 0x1
    • Button 9 = 0x1A
    • EQ = 0xD

  2. Create a program in the void loop() to activate a different function according to IR commands for the following:

    • Line Following - the program from Session Two

    • Obstacle Avoidance - the program from Gold Level of Session One

    • Driving pattern - the program created in Bronze Level of Session One

    • Remote control - a new function you will be writing in Gold Level of Session Three



    • You will need to create the necessary if/else if statements inside the if signal received to identify the command and run the correct function.

    • You will be comparing the IR command received to HEX values. Here is an example:
                            
        if (IrReceiver.decodedIRData.command == 0x15) 
        {
          chosenAction();
        }
                            
                          

    • You will also need to create a new function for the remote control program ready.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.

    New function:

                        
      void remoteControl()
      {
    
      }
                        
                      

    Remote command if statement:

                        
      if (IrReceiver.decode())
      {
    	  Serial.print("IR command received: 0x");
        Serial.println(IrReceiver.decodedIRData.command, HEX);
        if (IrReceiver.decodedIRData.command == 0xC) // button 0 on remote
        {
          lineFollow();
        }
        else if (IrReceiver.decodedIRData.command == 0x10) // button 1 on remote
        {
          ultrasonicCheck();
        }
        else if (IrReceiver.decodedIRData.command == 0x18) // button 7 on remote
        {
          setPath();
        }
        else if (IrReceiver.decodedIRData.command == 0x1A) // button 9 on remote
        {
          remoteControl();
        }
        IrReceiver.resume();
      }
                        
                      

                          
      //C++ code
      //
      
      #include <Servo.h>
      #include <IRremote.hpp>
      Servo myServo;  //creates a servo which can be called by name
      
      #define leftDrivePin 5
      #define rightDrivePin 6
      #define leftForwardPin 7
      #define leftReversePin 8
      #define rightForwardPin 11
      #define rightReversePin 9 
      #define servoPin 3
      #define leftPIRPin 2
      #define middlePIRPin 4
      #define rightPIRPin 10
      #define irReceiverPin 12
      
      int carSpeed = 200;
      int Echo = A4;
      int Trig = A5;
      int rightDistance = 0;
      int middleDistance = 0;
      int leftDistance = 0;
      
      void robotForward()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Forward");
      }
      
      void robotReverse()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Reverse");
      }
      
      void robotLeft()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, HIGH);
        digitalWrite(rightForwardPin, HIGH);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Spin Left");
      }
      
      void robotRight()
      {
        analogWrite(leftDrivePin, carSpeed);
        analogWrite(rightDrivePin, carSpeed);
        digitalWrite(leftForwardPin, HIGH);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, HIGH);
        Serial.println("Spin Right");
      }
      
      void robotStop()
      {
        analogWrite(leftDrivePin, 0);
        analogWrite(rightDrivePin, 0);
        digitalWrite(leftForwardPin, LOW);
        digitalWrite(leftReversePin, LOW);
        digitalWrite(rightForwardPin, LOW);
        digitalWrite(rightReversePin, LOW);
        Serial.println("Stop!");
      }
      
      int Distance_test()
      {
        digitalWrite(Trig, LOW);
        delayMicroseconds(2);
        digitalWrite(Trig, HIGH);
        delayMicroseconds(10);
        digitalWrite(Trig, LOW);
        float distance = pulseIn(Echo, HIGH);
        distance = distance / 2 / 29;
        return (int)distance;
      }
      
      void setup()
      {
        pinMode(leftForwardPin, OUTPUT);
        pinMode(leftReversePin, OUTPUT);
        pinMode(rightReversePin, OUTPUT);
        pinMode(rightForwardPin, OUTPUT);
        pinMode(leftDrivePin, OUTPUT);
        pinMode(rightDrivePin, OUTPUT);
        Serial.begin(9600);
        pinMode(Echo, INPUT);    
        pinMode(Trig, OUTPUT);
        myServo.attach(servoPin);
        pinMode(leftPIRPin, INPUT);
        pinMode(middlePIRPin, INPUT);
        pinMode(rightPIRPin, INPUT);
        IrReceiver.begin(irReceiverPin, ENABLE_LED_FEEDBACK);
      }
      
      void setPath()
      {
        robotForward();
        delay(2000);
        robotLeft();
        delay(1000);
        robotStop();
        delay(3000);
        robotReverse();
        delay(5000);
        robotRight();
        delay (4000);
        robotForward();
        delay(3000);
        robotStop();
        myServo.write(0);
        delay(500);
      }
      
      void ultrasonicCheck()
      {
        leftDistance = Distance_test();
        Serial.print(leftDistance);
        Serial.println("cm on left");
        myServo.write(90);
        delay(500);
        middleDistance = Distance_test();
        Serial.print(middleDistance);
        Serial.println("cm ahead");
        myServo.write(180);
        delay(500);
        rightDistance = Distance_test();
        Serial.print(rightDistance);
        Serial.println("cm on right");
        if (rightDistance > middleDistance && rightDistance > leftDistance)
        {
          Serial.print("Right is the safest direction");
          if (middleDistance < leftDistance)
          {
            Serial.print("Do not go forwards");
          }
          else
          {
            Serial.print("Do not go left");
          }
        } 
        else if (leftDistance > middleDistance)
        {
          Serial.print("Left is the safest direction");
          if (middleDistance < rightDistance)
          {
            Serial.print("Do not go forwards");
          }
          else
          {
            Serial.print("Do not go right");
          }
        }
        else
        {
          Serial.print("Forwards is the safest direction");
          if (leftDistance < rightDistance)
          {
            Serial.print("Do not go left");
          }
          else
          {
            Serial.print("Do not go right");
          }
        }
      }
      
      void lineFollow()
      {
        bool leftLine;
        bool midLine;
        bool rightLine;
        leftLine = digitalRead(leftPIRPin);
        midLine = digitalRead(middlePIRPin);
        rightLine = digitalRead(rightPIRPin);
        Serial.print("Left PIR: ");
        Serial.println(leftLine);
        Serial.print("Middle PIR: ");
        Serial.println(midLine);
        Serial.print("Right PIR: ");
        Serial.println(rightLine);
        if(leftLine && !midLine && !rightLine)
        {
          robotLeft();
          delay(100);
          robotStop();
        }
        else if(!leftLine && midLine && !rightLine)
        {
          robotForward();
          delay(100);
          robotStop();
        }
        else if(!leftLine && !midLine && rightLine)
        {
          robotRight();
          delay(100);
          robotStop();
        }
        else if(leftLine && midLine && !rightLine)
        {
          robotLeft();
          delay(50);
          robotStop();
        }
        else if(!leftLine && midLine && rightLine)
        {
          robotRight();
          delay(50);
          robotStop();
        }
        else if (!leftLine && !midLine && !rightLine)
        {
          robotRight();
          delay(200);
          robotStop();
        }                
        else if (leftLine && midLine && rightLine)
        {
          robotForward();
          delay(100);
          robotStop();
        }
        else
        {
          Serial.print("Error: Unexpected PIR readings");
        }
      }
      
      void remoteControl()
      {
    
      }
    
      void loop ()
      {
        if (IrReceiver.decode())
        {
          Serial.print("IR command received: 0x");
          Serial.println(IrReceiver.decodedIRData.command, HEX);
          if (IrReceiver.decodedIRData.command == 0xC) // button 0 on remote
          {
            lineFollow();
          }
          else if (IrReceiver.decodedIRData.command == 0x10) // button 1 on remote
          {
            ultrasonicCheck();
          }
          else if (IrReceiver.decodedIRData.command == 0x18) // button 7 on remote
          {
            setPath();
          }
          else if (IrReceiver.decodedIRData.command == 0x1A) // button 9 on remote
          {
            remoteControl();
          }
          IrReceiver.resume();
        }
      }                      
                          
                        




  1. Write the program for your new remote control function. This will need to include different remote commands for forwards, backwards, left, right, and stop.


    • This will use the motor functions we created in Session One.

    • Including the same serial print commands for the receiver as in the void loop(), will assist with any debugging and checks.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.


                        
      void remoteControl()
      {
        if (IrReceiver.decode())
        {
          Serial.print("IR command received: 0x");
          Serial.println(IrReceiver.decodedIRData.command, HEX);
          if (IrReceiver.decodedIRData.command == 0x11) // button 2 on remote
          {
            robotForward();
          }
          else if (IrReceiver.decodedIRData.command == 0x14) // button 4 on remote
          {
            robotLeft();
          }
          else if (IrReceiver.decodedIRData.command == 0x15) // button 5 on remote
          {
            robotStop();
          }
          else if (IrReceiver.decodedIRData.command == 0x16) // button 6 on remote
          {
            robotRight();
          }
          else if (IrReceiver.decodedIRData.command == 0x19) // button 8 on remote
          {
            robotReverse();
          }
        }
        IrReceiver.resume();
      }
                        
                      

  2. There is currently a problem with this program. The remote control function can only run once before exiting that mode because it returns to the void loop() after each action. Let us create a global variable we can use to store the mode selected in and use this to tell it when to exit the remote control program.


    • You can use an integer type variable with a number to represent each robot mode.

    • We will need to relocate where we resume the IR receiver to before the if statements of what to do according to the command. This means we need to create a local variable to store the command in before resuming. This will be a byte variable:

                            
        byte variableName = 0x0;
                            
                          

      This type of variable is needed to hold the HEX command value.

    • We can then add additional else if statements for the if (IrReceiver.decode) to keep the selected mode operating.

    • Select a different button on the IR remote to use for stopping and exiting a mode.

    Os ydych chi'n dal yn sownd, defnyddiwch y botwm ateb isod.

    Global variable:

                        
      int robotMode = 0;
                        
                      

    The if (IrReceiver.decode) statement using new command and mode variables:

                        
    if (IrReceiver.decode())
    {
      Serial.print("IR command received: 0x");
      Serial.println(IrReceiver.decodedIRData.command, HEX);
      byte cmd = IrReceiver.decodedIRData.command;
      IrReceiver.resume();
      if (cmd == 0xC) // button 0 on remote
      {
        robotMode = 1;
        lineFollow();
      }
      else if (cmd == 0x10) // button 1 on remote
      {
        robotMode = 2;
        ultrasonicCheck();
      }
      else if (cmd == 0x18) // button 7 on remote
      {
        robotMode = 3;
        setPath();
      }
      else if (cmd == 0x1A) // button 9 on remote
      {
        robotMode = 4;
          remoteControl();
      }
      else if (cmd == 0x2) // FUNC/STOP on remote
      {
        robotMode = 0;
      }
    }   
                        
                      

    New else if statements:

                        
      else if(robotMode == 1){
        lineFollow();
      }
      else if(robotMode == 2){
        ultrasonicCheck();
      }
      else if(robotMode == 3){
        setPath();
      }
      else if(robotMode == 4){
        remoteControl();
      }                    
                        
                      


                          
    //C++ code
    //
    
    #include 
    #include 
    Servo myServo;  //creates a servo which can be called by name
    
    #define leftDrivePin 5
    #define rightDrivePin 6
    #define leftForwardPin 7
    #define leftReversePin 8
    #define rightForwardPin 11
    #define rightReversePin 9 
    #define servoPin 3
    #define leftPIRPin 2
    #define middlePIRPin 4
    #define rightPIRPin 10
    #define irReceiverPin 12
    
    int carSpeed = 200;
    int Echo = A4;
    int Trig = A5;
    int rightDistance = 0;
    int middleDistance = 0;
    int leftDistance = 0;
    int robotMode = 0;
    
    void robotForward()
    {
      analogWrite(leftDrivePin, carSpeed);
      analogWrite(rightDrivePin, carSpeed);
      digitalWrite(leftForwardPin, HIGH);
      digitalWrite(leftReversePin, LOW);
      digitalWrite(rightForwardPin, HIGH);
      digitalWrite(rightReversePin, LOW);
      Serial.println("Forward");
    }
    
    void robotReverse()
    {
      analogWrite(leftDrivePin, carSpeed);
      analogWrite(rightDrivePin, carSpeed);
      digitalWrite(leftForwardPin, LOW);
      digitalWrite(leftReversePin, HIGH);
      digitalWrite(rightForwardPin, LOW);
      digitalWrite(rightReversePin, HIGH);
      Serial.println("Reverse");
    }
    
    void robotLeft()
    {
      analogWrite(leftDrivePin, carSpeed);
      analogWrite(rightDrivePin, carSpeed);
      digitalWrite(leftForwardPin, LOW);
      digitalWrite(leftReversePin, HIGH);
      digitalWrite(rightForwardPin, HIGH);
      digitalWrite(rightReversePin, LOW);
      Serial.println("Spin Left");
    }
    
    void robotRight()
    {
      analogWrite(leftDrivePin, carSpeed);
      analogWrite(rightDrivePin, carSpeed);
      digitalWrite(leftForwardPin, HIGH);
      digitalWrite(leftReversePin, LOW);
      digitalWrite(rightForwardPin, LOW);
      digitalWrite(rightReversePin, HIGH);
      Serial.println("Spin Right");
    }
    
    void robotStop()
    {
      analogWrite(leftDrivePin, 0);
      analogWrite(rightDrivePin, 0);
      digitalWrite(leftForwardPin, LOW);
      digitalWrite(leftReversePin, LOW);
      digitalWrite(rightForwardPin, LOW);
      digitalWrite(rightReversePin, LOW);
      Serial.println("Stop!");
    }
    
    int Distance_test()
    {
      digitalWrite(Trig, LOW);
      delayMicroseconds(2);
      digitalWrite(Trig, HIGH);
      delayMicroseconds(10);
      digitalWrite(Trig, LOW);
      float distance = pulseIn(Echo, HIGH);
      distance = distance / 2 / 29;
      return (int)distance;
    }
    
    void setup()
    {
      pinMode(leftForwardPin, OUTPUT);
      pinMode(leftReversePin, OUTPUT);
      pinMode(rightReversePin, OUTPUT);
      pinMode(rightForwardPin, OUTPUT);
      pinMode(leftDrivePin, OUTPUT);
      pinMode(rightDrivePin, OUTPUT);
      Serial.begin(9600);
      pinMode(Echo, INPUT);    
      pinMode(Trig, OUTPUT);
      myServo.attach(servoPin);
      pinMode(leftPIRPin, INPUT);
      pinMode(middlePIRPin, INPUT);
      pinMode(rightPIRPin, INPUT);
      IrReceiver.begin(irReceiverPin, ENABLE_LED_FEEDBACK);
    }
    
    void setPath()
    {
      robotForward();
      delay(2000);
      robotLeft();
      delay(1000);
      robotStop();
      delay(3000);
      robotReverse();
      delay(5000);
      robotRight();
      delay (4000);
      robotForward();
      delay(3000);
      robotStop();
      myServo.write(0);
      delay(500);
    }
    
    void ultrasonicCheck()
    {
      leftDistance = Distance_test();
      Serial.print(leftDistance);
      Serial.println("cm on left");
      myServo.write(90);
      delay(500);
      middleDistance = Distance_test();
      Serial.print(middleDistance);
      Serial.println("cm ahead");
      myServo.write(180);
      delay(500);
      rightDistance = Distance_test();
      Serial.print(rightDistance);
      Serial.println("cm on right");
      if (rightDistance > middleDistance && rightDistance > leftDistance)
      {
        Serial.print("Right is the safest direction");
        if (middleDistance < leftDistance)
        {
          Serial.print("Do not go forwards");
        }
        else
        {
          Serial.print("Do not go left");
        }
      } 
      else if (leftDistance > middleDistance)
      {
        Serial.print("Left is the safest direction");
        if (middleDistance < rightDistance)
        {
          Serial.print("Do not go forwards");
        }
        else
        {
          Serial.print("Do not go right");
        }
      }
      else
      {
        Serial.print("Forwards is the safest direction");
        if (leftDistance < rightDistance)
        {
          Serial.print("Do not go left");
        }
        else
        {
          Serial.print("Do not go right");
        }
      }
    }
    
    void lineFollow()
    {
      bool leftLine;
      bool midLine;
      bool rightLine;
      leftLine = digitalRead(leftPIRPin);
      midLine = digitalRead(middlePIRPin);
      rightLine = digitalRead(rightPIRPin);
      Serial.print("Left PIR: ");
      Serial.println(leftLine);
      Serial.print("Middle PIR: ");
      Serial.println(midLine);
      Serial.print("Right PIR: ");
      Serial.println(rightLine);
      if(leftLine && !midLine && !rightLine)
      {
        robotLeft();
        delay(100);
        robotStop();
      }
      else if(!leftLine && midLine && !rightLine)
      {
        robotForward();
        delay(100);
        robotStop();
      }
      else if(!leftLine && !midLine && rightLine)
      {
        robotRight();
        delay(100);
        robotStop();
      }
      else if(leftLine && midLine && !rightLine)
      {
        robotLeft();
        delay(50);
        robotStop();
      }
      else if(!leftLine && midLine && rightLine)
      {
        robotRight();
        delay(50);
        robotStop();
      }
      else if (!leftLine && !midLine && !rightLine)
      {
        robotRight();
        delay(200);
        robotStop();
      }                
      else if ((leftLine && midLine) && rightLine)
      {
        robotForward();
        delay(100);
        robotStop();
      }
      else
      {
        Serial.print("Error: Unexpected PIR readings");
      }
    
    }
    
    void remoteControl()
    {
      if (IrReceiver.decode())
      {
    	Serial.print("IR command received: 0x");
        Serial.println(IrReceiver.decodedIRData.command, HEX);
        if (IrReceiver.decodedIRData.command == 0x11) // button 2 on remote
        {
          robotForward();
        }
        else if (IrReceiver.decodedIRData.command == 0x14) // button 4 on remote
        {
          robotLeft();
        }
        else if (IrReceiver.decodedIRData.command == 0x15) // button 5 on remote
        {
          robotStop();
        }
        else if (IrReceiver.decodedIRData.command == 0x16) // button 6 on remote
        {
          robotRight();
        }
        else if (IrReceiver.decodedIRData.command == 0x19) // button 8 on remote
        {
          robotReverse();
        }
        else if (IrReceiver.decodedIRData.command == 0x2) // FUNC/STOP on remote
        {
          robotMode = 0;
        }
        IrReceiver.resume();
      }
    }
    
    void loop ()
    {
      if (IrReceiver.decode())
      {
        Serial.print("IR command received: 0x");
        Serial.println(IrReceiver.decodedIRData.command, HEX);
        byte cmd = IrReceiver.decodedIRData.command;
        IrReceiver.resume();
        if (cmd == 0xC) // button 0 on remote
        {
          robotMode = 1;
          lineFollow();
        }
        else if (cmd == 0x10) // button 1 on remote
        {
          robotMode = 2;
          ultrasonicCheck();
        }
        else if (cmd == 0x18) // button 7 on remote
        {
          robotMode = 3;
          setPath();
        }
        else if (cmd == 0x1A) // button 9 on remote
        {
          robotMode = 4;
            remoteControl();
        }
        else if (cmd == 0x2) // FUNC/STOP on remote
        {
        	robotMode = 0;
        }
      }
      else if(robotMode == 1){
        lineFollow();
      }
      else if(robotMode == 2){
        ultrasonicCheck();
      }
      else if(robotMode == 3){
        setPath();
      }
      else if(robotMode == 4){
        remoteControl();
      }
    }
    
    
                          
                        


  • Consider which buttons you have used for each control on the remote. Are they easy to operate? Rearrange if necessary. For example, is the reverse control under the forwards? is the left control on the left?

  • Add controls for increasing and decreasing the motor speeds whilst using the remote control.

  • Can you think of other behaviours you could create functions for and add remote control commands to activate?