Mini Tank Robot V3

Utrolig sej Mini Tank Robot fra Keyestudio som tilbyder masser af underholdning, men ikke mindst også læring! Det er nemlig muligt at programmere den med Arduinos IDE men også mixly. Derudover kan du modulært udskifte forskellige sensorer og aktuatorer. Så i denne lille sag for du altså noget for pengene! Nedenstående video vil gennemgå blot tre af de features robotten tilbyder, og samtidig også en kort video af byggeprocessen. På vores Github kan du finde alle kodeeksempler til robotten, du kan tilgå den her.


  • Vigtig viden
  • APP
  • Opbygning af Tank
  • Opbygning af Tank med Ultrasonisk sensor og photoresistorer
  • Opbygning af tank med Flame sensor og blæser
  • IR Remote
  • Ultrasonisk følgesvend
  • Multifunktionel tank
  • Programmering med Mixly
  • Vigtig viden

    For at programmere robotten kan det være nødvendigt at installere en driver på din Windows computer, som sikre at Computeren kan genkende Arduin Uno'en når den tilkobles. Driveren kan downloades her.

    Tanken har et 8x16 LED matrix display forrest, den har du mulighed for at costumize selv, der findes en fantastisk hjemmeside, hvor du let kan tegne det der skal være, hvorefter hjemmesiden selv konvertere tegningen til hex-kode, som du kan implementere i Arduino koden. Hjemmesiden kan findes her.

    Tanken anvender 2x 18650 batterier som ikke medfølger i pakken, derudover skal der også anvendes et CR2032 knapcelle batteri som IR-fjernbetjeningen anvender. Dette kan købes her på eBits!

    Det er muligt at lave to overordnede ændringer på robotten. Man kan forestille sig at du får to robotter for en robots pris. Henholdsvis Ultrasonisk med photoresistorer og flamme-sensor og blæser. Af nedenstående billede ses de "to" robotter

    APP

    Mini Tank Robot V3, er udstyret med et bluetooth modul så du har mulighed for at styre tanken og dens mange funktioner med telefonen. Det er muligt at anvende både android og apple telefoner. Du skal blot hente appen kaldet KeyesRobot.

     Google Play Store

    https://play.google.com/store/apps/details?id=com.keyestudio.keyestudio

    App Store

    Åben App Store→Søg KeyesRobot→download appen til telefonen

    Når appen åbnes trykkes der først på bluetoothknappen i højre hjørne, der popper nu en menu op hvor du kan connecte til Mini Tank Robot V3. Derefter vælges roboten afbilledet midt på skærmen. Nu præsenteres du for en masse funktioner som du kan anvende til at styre robotten. Se eventuelt præsentationsvideoen. 

     

     

    Opbygning af Tank

    Nedenstående billedeserie gennemgår opbygningen af selve tanken. Først samles 8x16 LED matrix, som skrues på akrylpladen.

    Herefter skrues ovenstående akrylplade med den monterede 8x16 matrix LED på akrylpladen.
    Her monteres Arduino Uno og det tilhørende motorshield på robotten.
    Når bluetooth modulet kobles på motorshieldet, er det vigitgt at tjekke at 5V og Ground stemmer overens mellem motorshield og bluetooth-modulet..
    Af nedenstående billede ses monteringen af jumpers. De kan altid vendes 90 grader for at få den pågældende motor til at køre i modsatte retningen.
    Af billedet ses monteringen af motor A og -B, til motorshieldet. Motor A kobles til højreside, hvis du ser robotten bagfra og motor B kobles til venstreside.


    Opbygning af Tank med Ultrasonisk sensor og photoresistorer

    Nedenstående vil gennemgå opsætning af robotten med ultrasonisk sensor og photoresistorerne. Først monteres den ultrasoniske sensor til den bukkede akrylplade.

    Derefter monteres servo-motoren, her er det vigitigt at servohjulet vender væk fra den ultrasoniske sensor.
      src="https://cdn.shopify.com/s/files/1/0444/6932/1894/files/Skaermbillede_2022-10-11_kl._16.41.03_480x480.jpg?v=1665564224" alt="" /> src="https://cdn.shopify.com/s/files/1/0444/6932/1894/files/Skaermbillede_2022-10-11_kl._16.41.17_480x480.jpg?v=1665564244" alt="">
     
      

    Opbygning af tank med Flame sensor og blæser

    Nedenstående billeder viser hvordan du kan skifte til blæser og flammesensorer. Det er vigtigt at bemærke at opkoblingskablerne også skal skiftes til de andre som medfølger i pakken. Men vær ikke bange, for dem som passer til photoresistorene passer ikke til flammesensorne.

    IR Remote

    Følgende eksempel baserer sig på at kunne styre robotten over infrarød. Der medølger en lille fjernbetjening i pakken som bruger et lille knapcelle-batteri på 3V. Disse kan fåes i din lokale købmand. 
    Nedenstående kode vil få dig kørende, det er muligt at køre frem, tilbage og til højre og venstre. Det er dog vigtigt at to biblioteker importeres til dine libraries. Den kan finde libraries under Dokumenter -> Arduino -> libraries.
    De to biblioteker findes her 

    #include <IRremote.h>
    IRrecv irrecv(A2);  //
    decode_results results;
    long ir_rec;  // used to save the IR value 
    
    //Array, used to save data of images, can be calculated by yourself or gotten from modulus tool
    unsigned char start01[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
    unsigned char front[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x12, 0x09, 0x12, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    unsigned char back[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x48, 0x90, 0x48, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    unsigned char left[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x28, 0x10, 0x44, 0x28, 0x10, 0x44, 0x28, 0x10, 0x00};
    unsigned char right[] = {0x00, 0x10, 0x28, 0x44, 0x10, 0x28, 0x44, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    unsigned char STOP01[] = {0x2E, 0x2A, 0x3A, 0x00, 0x02, 0x3E, 0x02, 0x00, 0x3E, 0x22, 0x3E, 0x00, 0x3E, 0x0A, 0x0E, 0x00};
    unsigned char clear[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    #define SCL_Pin  A5  //set the pin of clock to A5
    #define SDA_Pin  A4  //set the data pin to A4
    
    #define ML_Ctrl 4  //define the direction control pin of the left motor as 4
    #define ML_PWM 5   //define the PWM control pin of the left motor as 5
    #define MR_Ctrl 2  //define the direction control pin of the right sensor as 2
    #define MR_PWM 6    //define the PWM control pin of the right motor as 9
    
    void setup() {
      Serial.begin(9600);
      irrecv.enableIRIn();  //initialize the IR reception library
    
      pinMode(ML_Ctrl, OUTPUT);
      pinMode(ML_PWM, OUTPUT);
      pinMode(MR_Ctrl, OUTPUT);
      pinMode(MR_PWM, OUTPUT);
    
      pinMode(SCL_Pin, OUTPUT);
      pinMode(SDA_Pin, OUTPUT);
      matrix_display(clear); //Clear screens
      matrix_display(start01);  //display the image of start
    
    }
    
    void loop() {
      if (irrecv.decode(&results)) { //receive the value of IR remote
        ir_rec = results.value;
        String type = "UNKNOWN";
        String typelist[14] = {"UNKNOWN", "NEC", "SONY", "RC5", "RC6", "DISH", "SHARP", "PANASONIC", "JVC", "SANYO", "MITSUBISHI", "SAMSUNG", "LG", "WHYNTER"};
        if (results.decode_type >= 1 && results.decode_type <= 13) {
          type = typelist[results.decode_type];
        }
        Serial.print("IR TYPE:" + type + "  ");
        Serial.println(ir_rec, HEX);
        irrecv.resume();
      }
    
      switch (ir_rec) {
        case 0xFF629D: Car_front();     break;   //the command to go front
        case 0xFFA857: Car_back();      break;   //the command to go back
        case 0xFF22DD: Car_T_left();    break;   //the command to turn left
        case 0xFFC23D: Car_T_right();   break;   //the command to turn right
        case 0xFF02FD: Car_Stop();      break;   //the command to stop
        case 0xFF30CF: Car_left();      break;   //the command to rotate to left
        case 0xFF7A85: Car_right();     break;   //the command to rotate to right
        default: break;
      }
    
    }
    
    /***************motor works***************/
    void Car_front() {
      digitalWrite(MR_Ctrl, LOW);
      analogWrite(MR_PWM, 200);
      digitalWrite(ML_Ctrl, LOW);
      analogWrite(ML_PWM, 200);
      matrix_display(front);  //show the image to go front
    }
    
    void Car_back() {
      digitalWrite(MR_Ctrl, HIGH);
      analogWrite(MR_PWM, 200);
      digitalWrite(ML_Ctrl, HIGH);
      analogWrite(ML_PWM, 200);
      matrix_display(back);  //show the image to go back
    }
    
    void Car_left() {
      digitalWrite(MR_Ctrl, LOW);
      analogWrite(MR_PWM, 200);
      digitalWrite(ML_Ctrl, HIGH);
      analogWrite(ML_PWM, 200);
      matrix_display(left);  //show the image to rotate to left
    }
    
    void Car_right() {
      digitalWrite(MR_Ctrl, HIGH);
      analogWrite(MR_PWM, 200);
      digitalWrite(ML_Ctrl, LOW);
      analogWrite(ML_PWM, 200);
      matrix_display(right);  //show the image to rotate to right
    }
    
    void Car_Stop() {
      digitalWrite(MR_Ctrl, LOW);
      analogWrite(MR_PWM, 0);
      digitalWrite(ML_Ctrl, LOW);
      analogWrite(ML_PWM, 0);
      matrix_display(STOP01);  //show the image to stop
    }
    
    void Car_T_left() {
      digitalWrite(MR_Ctrl, LOW);
      analogWrite(MR_PWM, 255);
      digitalWrite(ML_Ctrl, LOW);
      analogWrite(ML_PWM, 150);
      matrix_display(left);  //show the image to turn left
    }
    
    void Car_T_right() {
      digitalWrite(MR_Ctrl, LOW);
      analogWrite(MR_PWM, 150);
      digitalWrite(ML_Ctrl, LOW);
      analogWrite(ML_PWM, 255);
      matrix_display(right);  //show the image to turn right
    }
    
    //this function is used for a dot matrix
    void matrix_display(unsigned char matrix_value[])
    {
      IIC_start();  //use the function to start transmitting data
      IIC_send(0xc0);  //select an address
      for (int i = 0; i < 16; i++) //image data have 16 characters
      {
        IIC_send(matrix_value[i]); //data to transmit pictures
      }
      IIC_end();   //end the data transmission of pictures
      IIC_start();
      IIC_send(0x8A);  //show control and select pulse width 4/16
      IIC_end();
    }
    
    //the condition that data starts transmitting
    void IIC_start()
    {
      digitalWrite(SDA_Pin, HIGH);
      digitalWrite(SCL_Pin, HIGH);
      delayMicroseconds(3);
      digitalWrite(SDA_Pin, LOW);
      delayMicroseconds(3);
      digitalWrite(SCL_Pin, LOW);
    }
    
    //the sign that transmission of data ends
    void IIC_end()
    {
      digitalWrite(SCL_Pin, LOW);
      digitalWrite(SDA_Pin, LOW);
      delayMicroseconds(3);
      digitalWrite(SCL_Pin, HIGH);
      delayMicroseconds(3);
      digitalWrite(SDA_Pin, HIGH);
      delayMicroseconds(3);
    }
    
    //transmit data
    void IIC_send(unsigned char send_data)
    {
      for (byte mask = 0x01; mask != 0; mask <<= 1) //ecah character has 8 digits, which is detected one by one
      {
        if (send_data & mask) { //set high or low levels in light of each bit(0 or 1)
          digitalWrite(SDA_Pin, HIGH);
        } else {
          digitalWrite(SDA_Pin, LOW);
        }
        delayMicroseconds(3);
        digitalWrite(SCL_Pin, HIGH); //pull up the clock pin SCL_Pin to end the transmission of data 
        delayMicroseconds(3);
        digitalWrite(SCL_Pin, LOW); //pull down the clock pin SCL_Pin to change signals of SDA 
      }
    }

    Ultrasonisk følgesvend

    Lille sjovt eksempel som bruger den ultrasoniske sensor til at følge efter din hånd eller genstand, men samtidig hvis hånden eller genstanden kommer for tæt på, vil robotten begynde at bakke væk. Her er koden, hvor det er muligt at ændre på de ønskede afstande. En god måde at lære at lege med ultrasoniske sensorer og forså hvordan man kan omregne til afstande.

    /*
      keyestudio Mini Tank Robot V3
      lesson 14
      Ultrasonic follow tank
      http://www.keyestudio.com
    */
    #define servoPin 10  //the pin of the servo
    
    #define ML_Ctrl 4  //define define the control pin of the left motor as 4
    #define ML_PWM 5   //define the PWM control pin of the left motor as 5
    #define MR_Ctrl 2  //define the control pin of the right motor as 2
    #define MR_PWM 6   //define the PWM control pin of the right motor as 9
    #define Trig 12
    #define Echo 13
    float distance;
    
    void setup() {
      pinMode(servoPin, OUTPUT);
      pinMode(Trig, OUTPUT);
      pinMode(Echo, INPUT);
      pinMode(ML_Ctrl, OUTPUT);
      pinMode(ML_PWM, OUTPUT);
      pinMode(MR_Ctrl, OUTPUT);
      pinMode(MR_PWM, OUTPUT);
      procedure(0); //set the angle of the servo to 90°
      delay(500); //delay in 500ms
    }
    void loop() {
      distance = checkdistance();  //distance assign the distance detected by an ultrasonic sensor
      if (distance >= 20 && distance <= 60) //the range to go front
      {
        Car_front();
      }
      else if (distance > 10 && distance < 20)  //the range to stop
      {
        Car_Stop();
      }
      else if (distance <= 10)  //the range to go back
      {
        Car_back();
      }
      else  //or else, stop
      {
        Car_Stop();
      }
    }
    void Car_front()
    {
      digitalWrite(MR_Ctrl, LOW);
      analogWrite(MR_PWM, 200);
      digitalWrite(ML_Ctrl, LOW);
      analogWrite(ML_PWM, 200);
    }
    void Car_back()
    {
      digitalWrite(MR_Ctrl,HIGH);
      analogWrite(MR_PWM,200);
      digitalWrite(ML_Ctrl,HIGH);
      analogWrite(ML_PWM,200);
    }
    void Car_left()
    {
      digitalWrite(MR_Ctrl, LOW);
      analogWrite(MR_PWM, 200);
      digitalWrite(ML_Ctrl, HIGH);
      analogWrite(ML_PWM, 200);
    }
    void Car_right()
    {
      digitalWrite(MR_Ctrl, HIGH);
      analogWrite(MR_PWM, 200);
      digitalWrite(ML_Ctrl, LOW);
      analogWrite(ML_PWM, 200);
    }
    void Car_Stop()
    {
      digitalWrite(MR_Ctrl, LOW);
      analogWrite(MR_PWM, 0);
      digitalWrite(ML_Ctrl, LOW);
      analogWrite(ML_PWM, 0);
    }
    
    //a function to control servos
    void procedure(byte myangle) {
      int pulsewidth;
      for (int i = 0; i < 5; i++) {
        pulsewidth = myangle * 11 + 500;  //calculate the value of pulse width
        digitalWrite(servoPin, HIGH);
        delayMicroseconds(pulsewidth);   //the time that high level maintains is pulse width
        digitalWrite(servoPin, LOW);
        delay((20 - pulsewidth / 1000));  //The cycle is 20ms
      }
    }
    //a function to control the ultrasonic sensor
    float checkdistance() {
      static float distance;
      digitalWrite(Trig, LOW);
      delayMicroseconds(2);
      digitalWrite(Trig, HIGH);
      delayMicroseconds(10);
      digitalWrite(Trig, LOW);
      distance = pulseIn(Echo, HIGH) / 58.20;  //2*29.1=58.2
      delay(10);
      return distance;
    }

    Multifunktionel tank

     

    Her er et eksempel hvor mange af de fede funktioner er implementeret. Der er udkommenteret funktioner som du selv kan vælge at bruge i stedet. I implementeringen er det muligt at styre robotten under bluetooth, samt tilgå blæser, matrix LED'erne og meget mere. 
    Det er vigtigt at fjerne bluetooth-modulet når du uploader nedenstående kode, da der ellers kan forekomme fejl ved upload. Derefter tilkobles bluetooth-modulet igen.

    /*
      keyestudio Mini Tank Robot V3
      lesson 22
      multiple functions
      http://www.keyestudio.com
    */
    #include <IRremote.h>
    IRrecv irrecv(A2);  //
    decode_results results;
    long ir_rec;  //used to save the IR value 
    
    //Array, used to save data of images, can be calculated by yourself or gotten from modulus tool
    unsigned char start01[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
    unsigned char STOP01[] = {0x2E, 0x2A, 0x3A, 0x00, 0x02, 0x3E, 0x02, 0x00, 0x3E, 0x22, 0x3E, 0x00, 0x3E, 0x0A, 0x0E, 0x00};
    unsigned char front[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x12, 0x09, 0x12, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    unsigned char back[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x48, 0x90, 0x48, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    unsigned char left[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x28, 0x10, 0x44, 0x28, 0x10, 0x44, 0x28, 0x10, 0x00};
    unsigned char right[] = {0x00, 0x10, 0x28, 0x44, 0x10, 0x28, 0x44, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    
    unsigned char Smile[] = {0x00, 0x00, 0x1c, 0x02, 0x02, 0x02, 0x5c, 0x40, 0x40, 0x5c, 0x02, 0x02, 0x02, 0x1c, 0x00, 0x00};
    unsigned char Disgust[] = {0x00, 0x00, 0x02, 0x02, 0x02, 0x12, 0x08, 0x04, 0x08, 0x12, 0x22, 0x02, 0x02, 0x00, 0x00, 0x00};
    unsigned char Happy[] = {0x02, 0x02, 0x02, 0x02, 0x08, 0x18, 0x28, 0x48, 0x28, 0x18, 0x08, 0x02, 0x02, 0x02, 0x02, 0x00};
    unsigned char Squint[] = {0x00, 0x00, 0x00, 0x41, 0x22, 0x14, 0x48, 0x40, 0x40, 0x48, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00};
    unsigned char Despise[] = {0x00, 0x00, 0x06, 0x04, 0x04, 0x04, 0x24, 0x20, 0x20, 0x26, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00};
    unsigned char Heart[] = {0x00, 0x00, 0x0C, 0x1E, 0x3F, 0x7F, 0xFE, 0xFC, 0xFE, 0x7F, 0x3F, 0x1E, 0x0C, 0x00, 0x00, 0x00};
    unsigned char eBits[] = {0x7e, 0x52, 0x52, 0x00, 0x7e, 0x4a, 0x7e, 0x00, 0x7e, 0x00, 0x02, 0x7e, 0x02, 0x5e, 0x52, 0x72
    };
    
    unsigned char clear[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
    
    #define SCL_Pin  A5  //set the pin of clock to A5
    #define SDA_Pin  A4  //set the data pin to A4
    
    #define ML_Ctrl 4  //define the direction control pin of the left motor as 4
    #define ML_PWM 5   //define the PWM control pin of the left motor as 5
    #define MR_Ctrl 2  //define the direction control pin of the right sensor as 2
    #define MR_PWM 6   //define the PWM control pin of the right motor as 6 
    
    char ble_val;      //used to save the Bluetooth value 
    byte speeds_L = 200; //the initial speed of the left motor is 200
    byte speeds_R = 200; // the initial speed of the right motor is 200
    String speeds_l, speeds_r; //receive PWM characters and convert them into PWM value
    
    //#define light_L_Pin D3   //define the pin of the left photoresistor
    //#define light_R_Pin A1   //define the pin of the right photoresistor
    int left_light;
    int right_light;
    
    int flame_L = 3; //define the analog port of the left flame sensor to A0
    int flame_R = A1; //define the analog port of the right flame sensor to A1
    
    //wire up the line tracking sensor
    #define L_pin  11  //left
    #define M_pin  7  //middle
    #define R_pin  8  //right
    int L_val, M_val, R_val, flame_valL, flame_valR;
    
    //the pin of 130 motor
    int INA = 12;
    int INB = 13;
    
    //#define Trig 12
    //#define Echo 13
    float distance;//Store the distance values detected by ultrasonic for following
    
    //Store the distance values detected by ultrasonic for obstacle avoidance
    int a;
    int a1;
    int a2;
    
    #define servoPin 10  //servo Pin
    
    bool flag;  // flage invarible, used to enter and exit a mode
    void setup() {
      Serial.begin(9600);
      irrecv.enableIRIn();  //Initialize the library of the IR remote
    
    //  pinMode(light_L_Pin, INPUT);
    //  pinMode(light_R_Pin, INPUT);
    
      //define the pins of sensors to INPUT
      pinMode(flame_L, INPUT);
      pinMode(flame_R, INPUT);
    
    //  pinMode(Trig, OUTPUT);
    //  pinMode(Echo, INPUT);
    
      pinMode(ML_Ctrl, OUTPUT);
      pinMode(ML_PWM, OUTPUT);
      pinMode(MR_Ctrl, OUTPUT);
      pinMode(MR_PWM, OUTPUT);
    
      pinMode(L_pin, INPUT); //set pins of the line tracking sensor to INPUT
      pinMode(M_pin, INPUT);
      pinMode(R_pin, INPUT);
    
      pinMode(servoPin, OUTPUT);
    
      pinMode(SCL_Pin, OUTPUT);
      pinMode(SDA_Pin, OUTPUT);
    
      pinMode(INA, OUTPUT);//set INA to OUTPUT
      pinMode(INB, OUTPUT);//set INB to OUTPUT
    
      matrix_display(clear);    //clear screens
      matrix_display(start01);  //show start
    
      procedure(90); //set the angle of the servo to 90°
    }
    
    void loop() {
      if (Serial.available()) //if there is data in the serial buffer
      {
        ble_val = Serial.read();
        Serial.println(ble_val);
        switch (ble_val) {
          case 'F': Car_front(); break; //the command to go front
    
          case 'B': Car_back(); break;  //the command to go back
    
          case 'L': Car_left(); break;  //the command to turn left
    
          case 'R': Car_right(); break; //the command to turn right
    
          case 'S': Car_Stop();  break; //the command to stop
    
          case 'e': Tracking();  break; //enter the line tracking mode
    
          case 'f': Confinement(); break;  //enter the confinement mode
    
    //      case 'g': Avoid(); break;  //enter the obstacle avoidance mode
    
    //      case 'h': Follow(); break;  //enter the line tracking mode
    //      case 'i': Light_following();  break;  //enter light following mode
    
          case 'j': Fire(); break;  //enter the mode to put out fire
    
          case 'c': fan_begin(); break;  //start the fan
    
          case 'd': fan_stop();  break;  //turn off the fan
    
          case 'u': speeds_l = Serial.readStringUntil('#'); speeds_L = String(speeds_l).toInt(); break; //start by receiving u, end by receiving characters # and convert into the integer
    
          case 'v': speeds_r = Serial.readStringUntil('#'); speeds_R = String(speeds_r).toInt(); break; //start by receiving u, end by receiving characters # and convert into the integer
          case 'k': matrix_display(Smile);    break;  //show "smile" face
          case 'l': matrix_display(Disgust);  break;  //show "disgust" face
          case 'm': matrix_display(Happy);    break;  //show "happy" face
          case 'n': matrix_display(Squint);   break;  //show "Sad" face
          case 'o': matrix_display(Despise);  break;  //show "despise" face
          case 'p': matrix_display(Heart);    break;  //show the hearbeat image
          case '1': matrix_display(eBits);    break;  //show the eBits image
          case 'z': matrix_display(clear);    break;  //clear images
    
          default: break;
        }
      }
      //the following signals are used to print out
      /*if(ble_val == 'x'){
        distance = checkdistance(); Serial.println(distance);
        delay(50);
      }else if(ble_val == 'w'){
        left_light = analogRead(light_L_Pin);
        Serial.println(left_light);
        delay(50);
      }else if(ble_val == 'y'){
        right_light = analogRead(light_R_Pin);
        Serial.println(right_light);
        delay(50);
      }*/
    
      
      if (irrecv.decode(&results)) { //receive the value detected by IR remote
        ir_rec = results.value;
        Serial.println(ir_rec, HEX);
        switch (ir_rec) {
          case 0xFF629D: Car_front();   break;   //the command to go front
          case 0xFFA857: Car_back();    break;   //the command  to go back
          case 0xFF22DD: Car_left();    break;   //the command to rotate to left
          case 0xFFC23D: Car_right();   break;   //the command to rotate to right
          case 0xFF02FD: Car_Stop();    break;   //the command to stop
          default: break;
        }
        irrecv.resume();
      }
    
    }
    
    /*****************obstacle avoidance******************/
    /*void Avoid()
    {
      flag = 0;
      while (flag == 0)
      {
        a = checkdistance();  //set the front distance detected by the ultrasonic sensor to a
        if (a < 20) {//when the front distance is less than 20cm
          Car_Stop();  //robot stops
          delay(500); //delay in 500ms
          procedure(180);  //servo platform turns left
          delay(500); //delay in 500ms
          a1 = checkdistance();  //set the left distance detected by the ultrasonic sensor to a1
          delay(100); //read value
    
          procedure(0); //servo platform turns right
          delay(500); //delay in 500ms
          a2 = checkdistance(); //set the right distance detected by the ultrasonic sensor to a2
          delay(100); //read value
    
          procedure(90);  //back to 90°
          delay(500);
          if (a1 > a2) { //the left distance is larger than the right
            Car_left();  //robots turn left
            delay(700);  //turn left for 700ms
          } else {
            Car_right(); //robot turns right
            delay(700);
          }
        }
        else { //if the front distance ≥20cm,robot goes front
          Car_front(); //go front
        }
        // receive the Bluetooth value to exit the loop
        if (Serial.available())
        {
          ble_val = Serial.read();
          if (ble_val == 'S')  //receive S
          {
            flag = 1;  //set flag to 1,exit the loop
            Car_Stop();
          }
        }
      }
    }*/
    
    /*******************line tracking****************/
    /*void Follow() {
      flag = 0;
      while (flag == 0) {
        distance = checkdistance();  //set the distance value to distance
        if (distance >= 20 && distance <= 60) //20≤ distance ≤60,go front
        {
          Car_front();
        }
        else if (distance > 10 && distance < 20)  //10< distance < 20, stop
        {
          Car_Stop();
        }
        else if (distance <= 10)  //distance≤ 10, go back
        {
          Car_back();
        }
        else  //or else, stop
        {
          Car_Stop();
        }
        if (Serial.available())
        {
          ble_val = Serial.read();
          if (ble_val == 'S')
          {
            flag = 1;  //exit the loop
            Car_Stop();
          }
        }
      }
    }*/
    
    /****************light following******************/
    /*void Light_following() {
      flag = 0;
      while (flag == 0) {
        left_light = analogRead(light_L_Pin);
        right_light = analogRead(light_R_Pin);
        if (left_light > 650 && right_light > 650) //go front
        {
          Car_front();
        }
        else if (left_light > 650 && right_light <= 650)  //turn left
        {
          Car_left();
        }
        else if (left_light <= 650 && right_light > 650) //turn right
        {
          Car_right();
        }
        else  //or else, stop
        {
          Car_Stop();
        }
        if (Serial.available())
        {
          ble_val = Serial.read();
          if (ble_val == 'S') {
            flag = 1;
            Car_Stop();
          }
        }
      }
    }*/
    
    /***************put out fire*****************/
    void Fire() {
      flag = 0;
      while (flag == 0) {
        //read the analog value of the flame sensor
        flame_valL = analogRead(flame_L);
        flame_valR = analogRead(flame_R);
        if (flame_valL <= 700 || flame_valR <= 700) {
          Car_Stop();
          fan_begin();
        } else {
          fan_stop();
          L_val = digitalRead(L_pin); //read the value of the left sensor
          M_val = digitalRead(M_pin); //read the value of the middle sensor
          R_val = digitalRead(R_pin); //read the value of the right one
    
          if (M_val == 1) { //the middle one detects black lines
            if (L_val == 1 && R_val == 0) { //if only the left one detects black lines, turn left
              Car_left();
            }
            else if (L_val == 0 && R_val == 1) { //if only the right one detects black lines, turn right
              Car_right();
            }
            else { //go front otherwise
              Car_front();
            }
          }
          else { //the middle one doesn't detect black lines
            if (L_val == 1 && R_val == 0) { //if only the left one detects black lines, turn left
              Car_left();
            }
            else if (L_val == 0 && R_val == 1) { //if only the right one detects black lines, turn right
              Car_right();
            }
            else { //stop otherwise 
              Car_Stop();
            }
          }
        }
        if (Serial.available())
        {
          ble_val = Serial.read();
          if (ble_val == 'S') {
            flag = 1;
            Car_Stop();
          }
        }
      }
      }
    
    /***************line tracking*****************/
    void Tracking() {
      flag = 0;
      while (flag == 0) {
        L_val = digitalRead(L_pin); //read the value of the left sensor
        M_val = digitalRead(M_pin); //read the value of the middle one
        R_val = digitalRead(R_pin); //read the value of the right one
        if (M_val == 1) { //the middle one detects black lines
          if (L_val == 1 && R_val == 0) { //if only the left one detects black lines, turn left
            Car_left();
          }
          else if (L_val == 0 && R_val == 1) { //if only the right one detects black lines, turn right
            Car_right();
          }
          else { //or else, go front
            Car_front();
          }
        }
        else { //the middle one doesn't detect the black line
          if (L_val == 1 && R_val == 0) { //if only the left one detect the black line,turn left
            Car_left();
          }
          else if (L_val == 0 && R_val == 1) { //if only the right one detects black lines, turn right
            Car_right();
          }
          else { //or else, stop
            Car_Stop();
          }
        }
        if (Serial.available())
        {
          ble_val = Serial.read();
          if (ble_val == 'S') {
            flag = 1;
            Car_Stop();
          }
        }
      }
    }
    
    /***************confinement*****************/
    void Confinement() {
      flag = 0;
      while (flag == 0) {
        L_val = digitalRead(L_pin); //read the value of the left sensor
        M_val = digitalRead(M_pin); //read the value of the middle one
        R_val = digitalRead(R_pin); //read the value of the right one
        if ( L_val == 0 && M_val == 0 && R_val == 0 ) { //if no sensor detects black lines, go front
          Car_front();
        }
        else { //or else, any the line tracking sensor can go back and turn left
          Car_back();
          delay(700);
          Car_left();
          delay(800);
        }
        if (Serial.available())
        {
          ble_val = Serial.read();
          if (ble_val == 'S') {
            flag = 1;
            Car_Stop();
          }
        }
      }
    
    }
    
    
    //he function to control the ultrasonic
    /*float checkdistance() {
      float distance;
      digitalWrite(Trig, LOW);
      delayMicroseconds(2);
      digitalWrite(Trig, HIGH);
      delayMicroseconds(10);
      digitalWrite(Trig, LOW);
      distance = pulseIn(Echo, HIGH) / 58.20;  // 2*29.1=58.2
      delay(10);
      return distance;
    }*/
    
    //the function to control servo
    void procedure(int myangle) {
      int pulsewidth;
      pulsewidth = map(myangle, 0, 180, 500, 2000);  //calculate the pulsewith value
      for (int i = 0; i < 5; i++) {
        digitalWrite(servoPin, HIGH);
        delayMicroseconds(pulsewidth);   //the time that high level maintains is pulse width
        digitalWrite(servoPin, LOW);
        delay((20 - pulsewidth / 1000));  //The cycle is 20ms
      }
    }
    
    /***************fan rotates*****************/
    void fan_begin() {
      digitalWrite(INA, LOW);
      digitalWrite(INB, HIGH);
    }
    
    /***************fan stops rotating*****************/
    void fan_stop() {
      digitalWrite(INA, LOW);
      digitalWrite(INB, LOW);
    }
    
    
    /***************dot matrix*****************/
    ///this function is used for the display of dot matrix 
    void matrix_display(unsigned char matrix_value[])
    {
      IIC_start();  //use the function to start transmitting data
      IIC_send(0xc0);  //select an address
      for (int i = 0; i < 16; i++) //image data have 16 characters
      {
        IIC_send(matrix_value[i]); //data to transmit pictures
      }
      IIC_end();   //end the data transmission of pictures
      IIC_start();
      IIC_send(0x8A);  //show control and select pulse width 4/16
      IIC_end();
    }
    
    //the condition that data starts transmitting
    void IIC_start()
    {
      digitalWrite(SDA_Pin, HIGH);
      digitalWrite(SCL_Pin, HIGH);
      delayMicroseconds(3);
      digitalWrite(SDA_Pin, LOW);
      delayMicroseconds(3);
      digitalWrite(SCL_Pin, LOW);
    }
    
    //transmit data
    void IIC_send(unsigned char send_data)
    {
      for (byte mask = 0x01; mask != 0; mask <<= 1) //ecah character has 8 digits, which is detected one by one
      {
        if (send_data & mask) { //set high or low levels in light of each bit(0 or 1)
          digitalWrite(SDA_Pin, HIGH);
        } else {
          digitalWrite(SDA_Pin, LOW);
        }
        delayMicroseconds(3);
        digitalWrite(SCL_Pin, HIGH); //pull up the clock pin SCL_Pin to end the transmission of data 
        delayMicroseconds(3);
        digitalWrite(SCL_Pin, LOW); //pull down the clock pin SCL_Pin to change signals of SDA 
      }
    }
    
    //the sign that transmission of data ends
    void IIC_end()
    {
      digitalWrite(SCL_Pin, LOW);
      digitalWrite(SDA_Pin, LOW);
      delayMicroseconds(3);
      digitalWrite(SCL_Pin, HIGH);
      delayMicroseconds(3);
      digitalWrite(SDA_Pin, HIGH);
      delayMicroseconds(3);
    }
    
    /***************motor runs***************/
    void Car_front() {
      digitalWrite(MR_Ctrl, LOW);
      analogWrite(MR_PWM, speeds_R);
      digitalWrite(ML_Ctrl, LOW);
      analogWrite(ML_PWM, speeds_L);
      matrix_display(front);  //show the image of going front
    }
    
    void Car_back() {
      digitalWrite(MR_Ctrl, HIGH);
      analogWrite(MR_PWM, speeds_R);
      digitalWrite(ML_Ctrl, HIGH);
      analogWrite(ML_PWM, speeds_L);
      matrix_display(back);  //show the image of going back
    }
    
    void Car_left() {
      digitalWrite(MR_Ctrl, LOW);
      analogWrite(MR_PWM, speeds_R);
      digitalWrite(ML_Ctrl, HIGH);
      analogWrite(ML_PWM, speeds_L);
      matrix_display(left);  //show the image of turning left
    }
    
    void Car_right() {
      digitalWrite(MR_Ctrl, HIGH);
      analogWrite(MR_PWM, speeds_R);
      digitalWrite(ML_Ctrl, LOW);
      analogWrite(ML_PWM, speeds_L);
      matrix_display(right);  //show the image of turning right
    }
    
    void Car_Stop() {
      digitalWrite(MR_Ctrl, LOW);
      analogWrite(MR_PWM, 0);
      digitalWrite(ML_Ctrl, LOW);
      analogWrite(ML_PWM, 0);
      matrix_display(STOP01);  //show the stop image
    }

    Programmering med Mixly

    Som nævnt er det også muligt at programmere ved hjælp af Mixly, som er mere at bygge med byggeklodser. En rigtig god indgang til verdenen af programmering. Programmet skal downloades og installeres på din PC.

    Windows  https://www.dropbox.com/s/mb3vxcn30jwvwxv/Mixly%20for%20windows.7z?dl=0 
    MAC https://www.dropbox.com/s/gcllwqpquwyy77c/Mixly_for_keyestudio_MacOS.zip?dl=0

    Når du har downloadet programmet er det vigtigt at Arduino UNO vælges som board.

    Nedenstående billede viser hvordan et simpelt blink-program ser ud når det er bygget op i Mixly.

    Du kan på vores GitHub finde kodeeksempler der bruger Mixly til programmering, linket kan findes her. 
    For at få en god og gennemgående introduktion til brugen af Mixly, forslår vi at du kigger på følgende dokumentation.

    Skriv kommentar!

    Relevante produkter

    TS101 digital loddekolbeTS101 digital loddekolbe i hånd
    TS101 digital loddekolbe med USB C forsyning
    Tilbudspris Fra 699,00 kr
    14 på lager
    TS80P USB-C Loddekolbe kitTS80P Loddekolbe
    TS80P USB-C Loddekolbe kit
    Tilbudspris Fra 799,00 kr
    2 på lager
    bruge Loddekolbe Renser til at rengøre loddekolbespidsenLoddekolbe Renser
    Luksus Loddekolbe renser
    Tilbudspris 89,00 kr
    8 på lager