Advertisement
Guest User

Untitled

a guest
Apr 21st, 2019
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 28.79 KB | None | 0 0
  1. e//Need to install Adafruit SSD1331, Adafruit GFX, PubSubClient Library
  2.  
  3.  
  4. //Line Following Related
  5. ///////////////////////////////////////////////////////////////////////////
  6. #include <Servo.h>
  7. #define MaxSpeed 2000// max speed of the robot
  8. #define BaseLeftSpeed 1850
  9. #define BaseRightSpeed 1190
  10. #define Kp 500 // experiment to determine this, start by something small that just makes your bot follow the line at a slow speed
  11. #define Kd 40
  12. #define echoPin 3
  13.  
  14. //OLED Related
  15. ///////////////////////////////////////////////////////////////////////////
  16. #define BLACK           0x0000
  17. #define BLUE            0x0006
  18. #define RED             0xF800
  19. #define GREEN           0x07E0
  20. #define CYAN            0x07FF
  21. #define MAGENTA         0xF81F
  22. #define YELLOW          0xFFE0
  23. #define WHITE           0xFFFF
  24. #define BACKGROUND      0x0000
  25.  
  26. #include <Adafruit_SSD1331.h>
  27.  
  28. //colorPAL related
  29. ///////////////////////////////////////////////////////////////////////////
  30. #include <SoftwareSerial.h>
  31.  
  32. const int sio = 51;      // ColorPAL connected to pin 51
  33. const int unused = 255;     // Non-existant pin # for SoftwareSerial
  34. const int sioBaud = 4800;
  35. const int waitDelay = 200;
  36.  
  37. // Received RGB values from ColorPAL
  38. int red;
  39. int grn;
  40. int blu;
  41.  
  42. // Set up two software serials on the same pin.
  43. SoftwareSerial serin(sio, unused);
  44. SoftwareSerial serout(unused, sio);
  45.  
  46. //Global
  47. ///////////////////////////////////////////////////////////////////////////
  48. String mode = "DEFAULT";
  49.  
  50. //TO BE DONE
  51. //const String DEFAULT_MODE = "D";
  52. //const String LINE_FOLLOWING_MODE = "LF";
  53. //const String LIGHT_TRACKING_MODE = "LT";
  54.  
  55. //D: Do nothing :)
  56. //LF: Line FOllowing
  57. //LT: Light Tracking
  58.  
  59.  
  60. //MQTT Related
  61. ///////////////////////////////////////////////////////////////////////////
  62. struct MqttMsg {
  63.   String topic;
  64.   String payload;
  65. };
  66.  
  67.  
  68. //Line Following Related
  69. ///////////////////////////////////////////////////////////////////////////
  70. Servo left, right;
  71. int l_qti, m_qti, r_qti; // left, middle, right
  72.  
  73. int lastError = 0;
  74. unsigned long total_count = 0;
  75. unsigned long count = 0;
  76. bool arrivedTarget = false;    // Boolean variable for target coordinates equal to current coordinates
  77.  
  78.  
  79. //Finding Red Spot Related
  80. ///////////////////////////////////////////////////////////////////////////
  81. bool redSpotDetected = false;  // Boolean variable for red spot is found
  82.  
  83.  
  84. //state set through network
  85. int xTarget = 5;  //must be larger than 0
  86. int yTarget = 5;
  87. int xCurrent = 0;
  88. int yCurrent = 0;
  89. String carDirection = "N";  //NSEW
  90. //end
  91.  
  92.  
  93. double pos = 0; // car position
  94.  
  95. const int thre1 = 80; // qti threshold 1: white
  96. const int thre2 = 300; // qti threshold 2
  97. const int thre3 = 500; // qti threshold 3: black
  98.  
  99. //Light Tracking Related
  100. ///////////////////////////////////////////////////////////////////////////
  101. double light = 0;
  102.  
  103. //OLED Related
  104. ///////////////////////////////////////////////////////////////////////////
  105. byte previousByte = LOW;
  106. byte currentByte = LOW;
  107. int counter = 0;
  108.  
  109. int mosi = 31; //--- connect this to the display module DIN pin (Serial Data) //31
  110. int sclk = 33; //--- connect this to the display module CLK pin (Serial Clock) //33
  111. int cs   = 35; //--- connect this to the display module CS  pin (Chip Select) //35
  112. int dc   = 37; //--- connect this to the display module D/C  pin (Data or Command) //37
  113. int rst  = 39; //--- connect this to the display module RES pin (Reset)  //39
  114.  
  115. Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, mosi, sclk, rst);
  116.  
  117. //GLOBAL VAR END
  118. ///////////////////////////////////////////////////////////////////////////
  119.  
  120.  
  121.  
  122. int get_qti(int pin) {
  123.   digitalWrite(pin, HIGH);
  124.   return analogRead(pin);
  125. }
  126.  
  127. long get_ultrasonic_distance() {
  128.   long duration, distance_in_cm;
  129.   // The sensor is triggered by a HIGH pulse of 10 or more microseconds.
  130.   // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  131.   pinMode(echoPin, OUTPUT);
  132.   digitalWrite(echoPin, LOW);
  133.   delayMicroseconds(2);
  134.   digitalWrite(echoPin, HIGH);
  135.   delayMicroseconds(10);
  136.   digitalWrite(echoPin, LOW);
  137.   pinMode(echoPin, OUTPUT);
  138.   digitalWrite(echoPin, HIGH);
  139.   duration = pulseIn(echoPin, HIGH);
  140.   distance_in_cm = (duration / 2) / 29.1;
  141.   return distance_in_cm;
  142. }
  143.  
  144. void backward() {
  145.   left.writeMicroseconds(1190);
  146.   right.writeMicroseconds(1850);
  147. }
  148.  
  149. void forward() {
  150.   left.writeMicroseconds(1850);
  151.   right.writeMicroseconds(1190);
  152. }
  153.  
  154. void stay() {
  155.   left.writeMicroseconds(1520);
  156.   right.writeMicroseconds(1520);
  157. }
  158.  
  159. void spin_left() {
  160.   left.writeMicroseconds(1190);
  161.   right.writeMicroseconds(1190);
  162. }
  163.  
  164. void spin_right() {
  165.   left.writeMicroseconds(1700);
  166.   right.writeMicroseconds(1700);
  167. }
  168.  
  169.  
  170. void spin_right90() {
  171.   // spin 90 degrees to right
  172.   spin_right();
  173.   delay(300);
  174.   while (get_qti(A0) < thre3) {
  175.     delay(2);
  176.   }
  177.   if (carDirection == "N")
  178.     carDirection = "E";
  179.   else if (carDirection == "E")
  180.     carDirection = "S";
  181.   else if (carDirection == "S")
  182.     carDirection = "W";
  183.   else if (carDirection == "W")
  184.     carDirection = "N";
  185. }
  186.  
  187. void spin_left90() {
  188.   // spin 90 degrees to left
  189.   spin_left();
  190.   delay(300);
  191.   while (get_qti(A2) < thre3) {
  192.     delay(2);
  193.   }
  194.   if (carDirection == "N")
  195.     carDirection = "W";
  196.   else if (carDirection == "E")
  197.     carDirection = "N";
  198.   else if (carDirection == "S")
  199.     carDirection = "E";
  200.   else if (carDirection == "W")
  201.     carDirection = "S";
  202. }
  203.  
  204. void spin180() {
  205.   spin_left();
  206.   delay(300);
  207.   while (get_qti(A2) < thre3) {
  208.     delay(2);
  209.   }
  210.   spin_left();
  211.   delay(300);
  212.   while (get_qti(A2) < thre3) {
  213.     delay(2);
  214.   }
  215.  
  216.   if (carDirection == "N")
  217.     carDirection = "S";
  218.   else if (carDirection == "E")
  219.     carDirection = "W";
  220.   else if (carDirection == "S")
  221.     carDirection = "N";
  222.   else if (carDirection == "W")
  223.     carDirection = "E";
  224. }
  225.  
  226. bool getpos(int l_qti, int m_qti, int r_qti, double &res) {
  227.   // return True if it detects the black line
  228.   // return False if it loses track of the black line
  229.   // res: result of predicting the position of the line
  230.   // -1 < res < 1, which is the position of the black line
  231.   // -ve res -> black line on the right
  232.   // +ve res -> black line on the left
  233.  
  234.   if (m_qti < thre1 && r_qti < thre1 && l_qti > thre2) {
  235.     // the line is closest to the left QTI sensor
  236.     // map the value of l_qti from 0 ~ 1023 to -1 ~ -0.5
  237.     res = l_qti / 1023.0 / 2.0 - 1;
  238.     return true;
  239.   }
  240.   if (m_qti < thre1 && l_qti < thre1 && r_qti > thre2) {
  241.     // the line is closest to the right QTI sensor
  242.     // map the value from 0 ~ 1023 to 0.5 ~ 1
  243.     res = 1 - r_qti / 1023.0 / 2.0;
  244.     return true;
  245.   }
  246.   if (l_qti < thre1 && m_qti < thre1 && r_qti < thre1) {
  247.     // All QTI sensors cannot find the line
  248.     return false;
  249.   }
  250.  
  251.   // Otherwise, the line is between the left and right QTI sensors
  252.   res = (double)(r_qti - l_qti) / (l_qti + m_qti + r_qti);
  253.   return true;
  254. }
  255.  
  256. void linefollow(double error) {
  257.   // difference in left/right wheel speed is proportional to
  258.   // the deviation of the line position
  259.  
  260.  
  261.   int motorSpeed = Kp * error + Kd * (error - lastError);
  262.   lastError = error;
  263.  
  264.   int rightMotorSpeed = BaseRightSpeed + motorSpeed;
  265.   int leftMotorSpeed = BaseLeftSpeed + motorSpeed;
  266.  
  267.   if (rightMotorSpeed > MaxSpeed ) rightMotorSpeed = MaxSpeed; // prevent the motor from going beyond max speed
  268.   if (leftMotorSpeed > MaxSpeed ) leftMotorSpeed = MaxSpeed; // prevent the motor from going beyond max speed
  269.   if (rightMotorSpeed < 0)rightMotorSpeed = 1516;
  270.   if (leftMotorSpeed < 0)leftMotorSpeed = 1516;
  271.  
  272.   left.writeMicroseconds(leftMotorSpeed);
  273.   right.writeMicroseconds(rightMotorSpeed);
  274.  
  275. }
  276.  
  277. //Setup
  278. ///////////////////////////////////////////////////////////////////////////
  279. void setup() {
  280.   Serial.begin(115200);
  281.   Serial1.begin(115200);
  282.  
  283.   //delay(2000); // Change to mqtt control
  284.   pinMode(2, OUTPUT); //debug light
  285.   pinMode(9, OUTPUT); // left servo
  286.   pinMode(10, OUTPUT); // right servo
  287.   pinMode(A0, INPUT); // right QTI
  288.   pinMode(A1, INPUT); // middle QTI
  289.   pinMode(A2, INPUT); // left QTI
  290.   pinMode(echoPin, OUTPUT);
  291.   left.attach(9);
  292.   right.attach(10);
  293.  
  294.   stay();
  295.  
  296.   //OLED
  297.   display.begin();
  298.   display.fillScreen(BLACK);
  299.   initOLED();
  300.  
  301.   //ColorPAL
  302.   reset();          // Send reset to ColorPal
  303.   serout.begin(sioBaud);
  304.   pinMode(sio, OUTPUT);
  305.   serout.print("= (00 $ m) !"); // Loop print values, see ColorPAL documentation
  306.   serout.end();       // Discontinue serial port for transmitting
  307.  
  308.   serin.begin(sioBaud);         // Set up serial port for receiving
  309.   pinMode(sio, INPUT);
  310.  
  311. }
  312.  
  313.  
  314. //Line Following Method
  315. ///////////////////////////////////////////////////////////////////////////
  316. long getUltrasonicDistance() {
  317.   long duration, distance_in_cm;
  318.   // The sensor is triggered by a HIGH pulse of 10 or more microseconds.
  319.   // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  320.   pinMode(echoPin, OUTPUT);
  321.   digitalWrite(echoPin, LOW);
  322.   delayMicroseconds(2);
  323.   digitalWrite(echoPin, HIGH);
  324.   delayMicroseconds(10);
  325.   digitalWrite(echoPin, LOW);
  326.   pinMode(echoPin, INPUT);
  327.   digitalWrite(echoPin, HIGH);
  328.   duration = pulseIn(echoPin, HIGH);
  329.   distance_in_cm = (duration / 2) / 29.1;
  330.   return distance_in_cm;
  331.  
  332. }
  333.  
  334. void lineFollowing()
  335. {
  336.   r_qti = get_qti(A0);
  337.   m_qti = get_qti(A1);
  338.   l_qti = get_qti(A2);
  339.  
  340.   getpos(l_qti, m_qti, r_qti, pos);
  341.  
  342.   //sendToMQTT(String("ECHODATA"),String(analogRead(echoPin)));
  343.   //Serial.print("PUB|ECHODATA:");
  344.  
  345.   if (xCurrent == xTarget && yCurrent == yTarget) {
  346.     stay();
  347.     arrivedTarget = true;
  348.  
  349.   } else {
  350.     // count how many interceptions have been passed
  351.     if (l_qti > thre3 && m_qti > thre3 && r_qti > thre3) {
  352.  
  353.       count++;
  354.     } else {
  355.       total_count = count;
  356.       count = 0;
  357.     }
  358.  
  359.     if (count > 10) { //intersection detected
  360.       total_count = 0;
  361.       count = 0;
  362.       forward();
  363.       delay(250);
  364.  
  365.       Serial.println("Intersection Detected");
  366.       Serial.println(carDirection);
  367.       Serial.println(xCurrent);
  368.       Serial.println(yCurrent);
  369.       Serial.println("");
  370.  
  371.  
  372.  
  373.       if (carDirection == "N") {
  374.         yCurrent++;
  375.       } else if (carDirection == "S") {
  376.         yCurrent--;
  377.       } else if (carDirection == "E") {
  378.         xCurrent++;
  379.       } else if (carDirection == "W") {
  380.         xCurrent--;
  381.       }
  382.       if (xCurrent == xTarget && yCurrent == yTarget) {
  383.         if (xCurrent == 0 && yCurrent == 0 && carDirection == "S" || xCurrent == 0 && yCurrent == 5 && carDirection == "W" || xCurrent == 5 && yCurrent == 0 && carDirection == "E" || xCurrent == 5 && yCurrent == 5 && carDirection == "N") {
  384.           spin_left90();
  385.         } else if (xCurrent == 0 && yCurrent == 0 && carDirection == "W" || xCurrent == 0 && yCurrent == 5 && carDirection == "N" || xCurrent == 5 && yCurrent == 0 && carDirection == "S" || xCurrent == 5 && yCurrent == 5 && carDirection == "E") {
  386.           spin_right90();
  387.         } else if ( xCurrent == 0 && carDirection == "W" || xCurrent == 5 && carDirection == "E" || yCurrent == 0 && carDirection == "S" || yCurrent == 5 && carDirection == "N") {
  388.           spin180();
  389.         }
  390.  
  391.       }
  392.  
  393.  
  394.       if (xCurrent > xTarget) {
  395.         if (yCurrent > yTarget) {
  396.           if (carDirection == "N") {
  397.             spin_left90();
  398.           } else if (carDirection == "E") {
  399.             spin_right90();
  400.           } else if (carDirection == "S") {
  401.  
  402.           } else if (carDirection == "W") {
  403.  
  404.           }
  405.         } else if (yCurrent == yTarget) {
  406.           if (carDirection == "E") {
  407.             //spin180();
  408.           } else if (carDirection == "N") {
  409.             spin_left90();
  410.           } else if (carDirection == "S") {
  411.             spin_right90();
  412.           } else if (carDirection == "W") {
  413.  
  414.           }
  415.         } else if (yCurrent < yTarget) {
  416.           if (carDirection == "E") {
  417.             spin_left90();
  418.           } else if (carDirection == "S") {
  419.             //spin180();
  420.             spin_right90();
  421.           } else if (carDirection == "N") {
  422.  
  423.           } else if (carDirection == "W") {
  424.             //spin_right90();
  425.           }
  426.         }
  427.       } else if (xCurrent == xTarget) {
  428.         if (yCurrent > yTarget) {
  429.           if (carDirection == "E") {
  430.             spin_right90();
  431.           } else if (carDirection == "W") {
  432.             spin_left90();
  433.           } else if (carDirection == "S") {
  434.  
  435.           } else if (carDirection == "N") {
  436.             //spin180();
  437.           }
  438.         } else if (yCurrent < yTarget) {
  439.           if (carDirection == "E") {
  440.             spin_left90();
  441.           } else if (carDirection == "W") {
  442.             spin_right90();
  443.           } else if (carDirection == "S") {
  444.             //spin180();
  445.           } else if (carDirection == "N") {
  446.  
  447.           }
  448.         }
  449.  
  450.       } else if (xCurrent < xTarget) {
  451.         if (yCurrent > yTarget) {
  452.           if (carDirection == "W") {
  453.             //spin180();
  454.             spin_left90();
  455.           }
  456.           else if (carDirection == "N") {
  457.             spin_right90();
  458.           }
  459.           else if (carDirection == "S") {
  460.             //spin_left90();
  461.           }
  462.           else if (carDirection == "E") {
  463.  
  464.           }
  465.         }
  466.         else if (yCurrent == yTarget) {
  467.           if (carDirection == "S") {
  468.             spin_left90();
  469.           }
  470.           else if (carDirection == "N") {
  471.             spin_right90();
  472.           }
  473.           else if (carDirection == "W") {
  474.             //spin180();
  475.           }
  476.           else if (carDirection == "E") {
  477.  
  478.           }
  479.  
  480.         }
  481.         else if (yCurrent < yTarget) {
  482.           if (carDirection == "S") {
  483.             spin_left90();
  484.           }
  485.           else if (carDirection == "W") {
  486.             spin_right90();
  487.           }
  488.           else if (carDirection == "N") {
  489.  
  490.           } else if (carDirection == "E") {
  491.  
  492.           }
  493.         }
  494.       }
  495.  
  496.       if (getUltrasonicDistance() < 18) { // obstacles
  497.         // Four Boundary Cases
  498.         if (carDirection == "N" && xCurrent == 5 || carDirection == "W" && yCurrent == 5 || carDirection == "S" && xCurrent == 0 || carDirection == "E" && yCurrent == 0) {
  499.           spin_left90();
  500.         } else {
  501.           spin_right90();
  502.         }
  503.  
  504.       }
  505.  
  506.  
  507.       Serial1.print("PUB|LF:");
  508.       Serial1.print(xCurrent);
  509.       Serial1.print(",");
  510.       Serial1.print(yCurrent);
  511.       Serial1.print(",");
  512.       Serial1.println(carDirection);
  513.  
  514.       String coordianteMessage = "Mode: \nLine Following\n";
  515.       coordianteMessage += xCurrent;
  516.       coordianteMessage += ",";
  517.       coordianteMessage += yCurrent;
  518.       coordianteMessage += ",";
  519.       coordianteMessage += carDirection;
  520.  
  521.       printToOLED(coordianteMessage, 2);
  522.  
  523.     } else {
  524.       // follow the line otherwise
  525.       linefollow(pos);
  526.     }
  527.   }
  528. }
  529.  
  530. void lineFollowingChageCoordinate(String payload)
  531. {
  532.  
  533.   Serial.print("Change Coordinate: ");
  534.   Serial.println(payload);
  535.  
  536.   char LF_delim[] = ",";
  537.  
  538.   int xNewTarget = 0;
  539.   int yNewTarget = 0;
  540.   String newDirection = "";
  541.  
  542.   // create char* that keeps str for subsequent operations
  543.   char* c_str = new char[payload.length() + 1];
  544.   strcpy(c_str, payload.c_str());
  545.  
  546.   // The C library function char *strtok(char *str, const char *delim)
  547.   // breaks string str into a series of tokens using the delimiter delim.
  548.   char* sub_str = strtok(c_str, LF_delim);
  549.  
  550.   xNewTarget = atoi((char *)sub_str);
  551.  
  552.   sub_str = strtok(NULL, LF_delim);
  553.  
  554.   yNewTarget = atoi((char *)sub_str);
  555.  
  556.   sub_str = strtok(NULL, LF_delim);
  557.  
  558.   if (sub_str != NULL) {
  559.     newDirection = String(sub_str);
  560.   }
  561.  
  562.   Serial.print(xNewTarget);
  563.   Serial.print(" ");
  564.   Serial.print(yNewTarget);
  565.   Serial.print(" ");
  566.  
  567.   char direction_c = newDirection[0];
  568.   if (direction_c != '\0' && (direction_c == 'N' || direction_c == 'E' || direction_c == 'S' || direction_c == 'W'))
  569.   {
  570.     Serial.println(direction_c);
  571.     lineFollowingSetCoordinate(xNewTarget, yNewTarget, String(direction_c));
  572.   }
  573.   else
  574.   {
  575.     Serial.println("Same Direction!");
  576.     lineFollowingSetCoordinate(xNewTarget, yNewTarget, "");
  577.   }
  578.  
  579. }
  580.  
  581.  
  582. void lineFollowingSetCurrentCoordinate(String payload)
  583. {
  584.  
  585.   Serial.print("Set Coordinate: ");
  586.   Serial.println(payload);
  587.  
  588.   char LF_delim[] = ",";
  589.  
  590.   int xNewCurrent = 0;
  591.   int yNewCurrent = 0;
  592.   String newDirection = "";
  593.  
  594.   // create char* that keeps str for subsequent operations
  595.   char* c_str = new char[payload.length() + 1];
  596.   strcpy(c_str, payload.c_str());
  597.  
  598.   // The C library function char *strtok(char *str, const char *delim)
  599.   // breaks string str into a series of tokens using the delimiter delim.
  600.   char* sub_str = strtok(c_str, LF_delim);
  601.  
  602.   xNewCurrent = atoi((char *)sub_str);
  603.  
  604.   sub_str = strtok(NULL, LF_delim);
  605.  
  606.   yNewCurrent = atoi((char *)sub_str);
  607.  
  608.   sub_str = strtok(NULL, LF_delim);
  609.  
  610.   if (sub_str != NULL) {
  611.     newDirection = String(sub_str);
  612.   }
  613.  
  614.   Serial.print(xNewCurrent);
  615.   Serial.print(" ");
  616.   Serial.print(yNewCurrent);
  617.   Serial.print(" ");
  618.  
  619.   char direction_c = newDirection[0];
  620.   if (direction_c != '\0' && (direction_c == 'N' || direction_c == 'E' || direction_c == 'S' || direction_c == 'W'))
  621.   {
  622.     Serial.println(direction_c);
  623.     xCurrent = xNewCurrent;
  624.     yCurrent = yNewCurrent;
  625.     carDirection = direction_c;
  626.   }
  627.   else
  628.   {
  629.     Serial.println("Same Direction!");
  630.     xCurrent = xNewCurrent;
  631.     yCurrent = yNewCurrent;
  632.   }
  633.  
  634.   String coordianteMessage = "Mode: \nLine Following\n";
  635.   coordianteMessage += xCurrent;
  636.   coordianteMessage += ",";
  637.   coordianteMessage += yCurrent;
  638.   coordianteMessage += ",";
  639.   coordianteMessage += carDirection;
  640.  
  641.   printToOLED(coordianteMessage, 2);
  642. }
  643.  
  644. void lineFollowingSetCoordinate(int x, int y, String direction)
  645. {
  646.   xTarget = x;
  647.   yTarget = y;
  648.  
  649.   if (direction != "")
  650.   {
  651.     carDirection = direction;
  652.   }
  653.  
  654.   lastError = 0;
  655.   total_count = 0;
  656.   count = 0;
  657.   pos = 0; // car position
  658.   Serial.println("Coordinate Chage Success!");
  659.   Serial.print(xTarget);
  660.   Serial.print(",");
  661.   Serial.print(yTarget);
  662.   if (direction != "")
  663.   {
  664.     Serial.print(",");
  665.     Serial.println(direction);
  666.   }
  667.  
  668.  
  669.   Serial1.print("PUB|LF:");
  670.   Serial1.print(xTarget);
  671.   Serial1.print(",");
  672.   Serial1.print(yTarget);
  673.   if (direction != "")
  674.   {
  675.     Serial1.print(",");
  676.     Serial1.println(direction);
  677.   }
  678.   else
  679.   {
  680.     Serial1.println();
  681.   }
  682. }
  683.  
  684. //Light Tracking Method
  685. ///////////////////////////////////////////////////////////////////////////
  686. void getLight() {
  687.   int left = analogRead(A3);
  688.   int right = analogRead(A4);
  689.   int diff = left - right + 120;
  690.   light = (diff ) / 200.0 * (-1) ;
  691. }
  692.  
  693. void lightTracking() {
  694.   r_qti = get_qti(A0);
  695.   m_qti = get_qti(A1);
  696.   l_qti = get_qti(A2);
  697.  
  698.   getLight();
  699.   linefollow(light);
  700. }
  701.  
  702. //Finding Red Spot Method
  703. ///////////////////////////////////////////////////////////////////////////
  704. void findingRedSpot() {
  705.   xCurrent = 0;
  706.   yCurrent = 0;
  707.   xTarget = 5;
  708.   yTarget = 0;
  709.  
  710.   while(!redSpotDetected && !(xCurrent == 5 && yCurrent == 2)){
  711.     readData();
  712.     lineFollowing();
  713.     if(arrivedTarget){    // Change target coordinates, so the car follows an 'S' shape route
  714.       yTarget += 1;
  715.       if(xTarget == 5){
  716.         xTarget = 0;
  717.       }else if(xTarget == 0){
  718.         xTarget = 5;
  719.       }
  720.       arrivedTarget = false;
  721.     }
  722.   }
  723.  
  724.   stay();
  725.   if(redSpotDetected){
  726.     String msg = "Red spot found in: ";
  727.     msg += xCurrent ;
  728.     msg += ", ";
  729.     msg += yCurrent;
  730.     printToOLED(msg, 1);
  731.   }else{
  732.     printToOLED("Red spot is not found", 1);
  733.   }
  734.  
  735. }
  736.  
  737. // Reset ColorPAL; see ColorPAL documentation for sequence
  738. void reset() {
  739.   delay(200);
  740.   pinMode(sio, OUTPUT);
  741.   digitalWrite(sio, LOW);
  742.   pinMode(sio, INPUT);
  743.   while (digitalRead(sio) != HIGH);
  744.   pinMode(sio, OUTPUT);
  745.   digitalWrite(sio, LOW);
  746.   delay(80);
  747.   pinMode(sio, INPUT);
  748.   delay(waitDelay);
  749. }
  750.  
  751. // Read color pixels data
  752. void readData() {
  753.   char buffer[32];
  754.  
  755.   if (serin.available() > 0) {
  756.     // Wait for a $ character, then read three 3 digit hex numbers
  757.     buffer[0] = serin.read();
  758.     if (buffer[0] == '$') {
  759.       for(int i = 0; i < 9; i++) {
  760.         while (serin.available() == 0);     // Wait for next input character
  761.         buffer[i] = serin.read();
  762.         if (buffer[i] == '$')               // Return early if $ character encountered
  763.           return;
  764.       }
  765.       parseAndPrint(buffer);
  766.       delay(10);
  767.     }
  768.   }
  769. }
  770.  
  771. // Parse the hex data into integers
  772. void parseAndPrint(char * data) {
  773.   sscanf (data, "%3x%3x%3x", &red, &grn, &blu);
  774.   char buffer[32];
  775.   sprintf(buffer, "R%4.4d G%4.4d B%4.4d", red, grn, blu);
  776.   if (red > 140 && grn < 80 && blu < 130) {   // Pixel data for Red color
  777.     redSpotDetected = true;
  778.     Serial.println("RED is detected");
  779.   }
  780. }
  781.  
  782.  
  783.  
  784. //MQTT Related Method
  785. ///////////////////////////////////////////////////////////////////////////
  786. MqttMsg parse_mqtt_msg(String str) {
  787.  
  788.   MqttMsg mqtt_msg;
  789.   char delim[] = "|";
  790.  
  791.   // create char* that keeps str for subsequent operations
  792.   char* c_str = new char[str.length() + 1];
  793.   strcpy(c_str, str.c_str());
  794.  
  795.   // The C library function char *strtok(char *str, const char *delim)
  796.   // breaks string str into a series of tokens using the delimiter delim.
  797.   char* sub_str = strtok(c_str, delim);
  798.  
  799.   //Check Topic
  800.   if (strcmp(sub_str, "Topic") != 0) {
  801.     return mqtt_msg; // str does not contain MQTT message
  802.   }
  803.  
  804.   sub_str = strtok(NULL, delim);
  805.  
  806.   if (sub_str == NULL) {
  807.     return mqtt_msg; // str not complete
  808.   }
  809.   mqtt_msg.topic = String(sub_str);
  810.  
  811.   //Skip Tab
  812.   sub_str = strtok(NULL, delim);
  813.  
  814.   //Check Payload
  815.   sub_str = strtok(NULL, delim);
  816.   if (sub_str == NULL) {
  817.     return mqtt_msg; // str not complete
  818.   }
  819.   sub_str = strtok(NULL, delim);
  820.  
  821.   mqtt_msg.payload = String(sub_str);
  822.  
  823.   return mqtt_msg;
  824. }
  825.  
  826. void sendToMQTT(String topic, String payload)
  827. { //example: sendToMQTT("Topic","Payload");
  828.   char topic_c[1024];
  829.   char payload_c[1024];
  830.   topic.toCharArray(topic_c, topic.length());
  831.   payload.toCharArray(payload_c, payload.length());
  832.   Serial1.print("PUB|");
  833.   Serial1.print(topic);
  834.   Serial1.print(":");
  835.   Serial1.println(payload);
  836. }
  837.  
  838. //OLED Method
  839. ///////////////////////////////////////////////////////////////////////////
  840. void initOLED() {
  841.   display.fillScreen(BLACK);
  842.   display.setCursor(15, 5);
  843.   display.setTextColor(WHITE);
  844.   display.setTextSize(2);
  845.   display.println("HKUEEE");
  846.   display.setCursor(0, 25);
  847.   display.setTextColor(CYAN);
  848.   display.setTextSize(2);
  849.   display.println("IDP 2018");
  850.   display.setCursor(15, 50);
  851.   display.setTextColor(YELLOW);
  852.   display.setTextSize(2);
  853.   display.println("Final");
  854. }
  855.  
  856. void printToOLED(String msg, int fontSize)
  857. {
  858.   display.fillScreen(BLACK);
  859.   display.setTextColor(WHITE);
  860.   display.setTextSize(fontSize);
  861.   display.setCursor(0, 0);
  862.   display.print(msg);
  863. }
  864.  
  865. //Main Loop
  866. ///////////////////////////////////////////////////////////////////////////
  867. void loop() {
  868.   // Serial.println() outputs to Serial Monitor
  869.   // Serial1.println() outputs to ESP8266
  870.  
  871.   /* Get MQTT messages from ESP */
  872.   while (Serial1.available()) {
  873.     String serial_str;
  874.     serial_str = Serial1.readStringUntil('\n');
  875.     Serial.println(serial_str);
  876.  
  877.     MqttMsg mqtt_msg = parse_mqtt_msg(serial_str);
  878.  
  879.     if (mqtt_msg.topic[0] != '\0' && mqtt_msg.payload[0] != '\0')
  880.     {
  881.       Serial.print(F("Arduino Received - Topic: "));
  882.       Serial.print(mqtt_msg.topic);
  883.       Serial.print(F("\tPayload: "));
  884.       Serial.println(mqtt_msg.payload);
  885.       Serial1.println("PUB|Debug:ACK"); //Pub ACK to MQTT after successfully received a message from ESP
  886.  
  887.       char topic_c[100];
  888.       char payload_c[100];
  889.  
  890.       mqtt_msg.payload.toCharArray(payload_c, mqtt_msg.payload.length());
  891.  
  892.       //Car 1
  893.       if (mqtt_msg.topic == "JARVIS/server/1/MODE" || mqtt_msg.topic == "JARVIS/server/MODE")
  894.       //Car 2
  895.       //if (mqtt_msg.topic == "JARVIS/server/2/MODE" || mqtt_msg.topic == "JARVIS/server/MODE")
  896.       {
  897.         //Determine Mode
  898.         //Serial.println(mqtt_msg.payload);
  899.         if (strcmp(payload_c, "D") == 0)
  900.         {
  901.           mode = "D";
  902.           Serial.println("Mode Changed: DEFAULT");
  903.           sendToMQTT("Mode", "Default");
  904.           printToOLED("Mode: \nDefault", 2);
  905.         }
  906.         else if (strcmp(payload_c, "LF") == 0)
  907.         {
  908.           mode = "LF";
  909.           Serial.println("Mode Changed: Line Following");
  910.           Serial1.print("PUB|LF:");
  911.           Serial1.print(xCurrent);
  912.           Serial1.print(",");
  913.           Serial1.print(yCurrent);
  914.           Serial1.print(",");
  915.           Serial1.println(carDirection);
  916.           sendToMQTT("Mode", "Line Following");
  917.         }
  918.         else if (strcmp(payload_c, "RED") == 0)
  919.         {
  920.           mode = "RED";
  921.           Serial.println("Mode Changed: Finding Red Spot");
  922.           sendToMQTT("Mode", "Finding Red Spot");
  923.           printToOLED("Mode: \nFinding Red Spot", 2);
  924.         }
  925.         else if (strcmp(payload_c, "LT") == 0)
  926.         {
  927.           mode = "LT";
  928.           Serial.println("Mode Changed: Light Tracking");
  929.           sendToMQTT("Mode", "Light Tracking");
  930.           printToOLED("Mode: \nLight Tracking", 2);
  931.         }
  932.         else if (strcmp(payload_c, "TR") == 0)
  933.         {
  934.           spin_right90();
  935.           Serial.println("Turn Right");
  936.           sendToMQTT("Debug", "Turn Right");
  937.           printToOLED("Turn Right", 2);
  938.         }
  939.         else if (strcmp(payload_c, "TL") == 0)
  940.         {
  941.           spin_left90();
  942.           Serial.println("Turn Left");
  943.           sendToMQTT("Debug", "Turn Left");
  944.           printToOLED("Turn Left", 2);
  945.         }
  946.         else
  947.         {
  948.           Serial.println("No such mode :(");
  949.           sendToMQTT("Mode", "Mode NA");
  950.         }
  951.       }
  952.  
  953.       //Collision
  954.       //Car 1
  955.       else if (mqtt_msg.topic == "JARVIS/server/1/Collision" || mqtt_msg.topic == "JARVIS/server/Collision")
  956.       //Car 2
  957.       //else if (mqtt_msg.topic == "JARVIS/server/2/Collision" || mqtt_msg.topic == "JARVIS/server/Collision")
  958.       {
  959.         if (strcmp(payload_c, "Stop") == 0)
  960.         {
  961.           mode = "D";
  962.           sendToMQTT("Collision", "Stop");
  963.           printToOLED("Collision: \nStop", 2);
  964.         }
  965.         else if (strcmp(payload_c, "Turn") == 0)
  966.         {
  967.           // Four Boundary Cases
  968.           if (carDirection == "N" && xCurrent == 5 || carDirection == "W" && yCurrent == 5 || carDirection == "S" && xCurrent == 0 || carDirection == "E" && yCurrent == 0) {
  969.             spin_left90();
  970.           } else {
  971.             spin_right90();
  972.           }
  973.           sendToMQTT("Collision", "Turn");
  974.           printToOLED("Collision: \nTurn", 2);
  975.         }
  976.         else if (strcmp(payload_c, "Move") == 0)
  977.         {
  978.           mode = "LF";
  979.           sendToMQTT("Collision", "Move");
  980.           printToOLED("Collision: \nMove", 2);
  981.         }
  982.         else if (strcmp(payload_c, "Next") == 0)
  983.         {
  984.           sendToMQTT("Collision", "Next");
  985.           printToOLED("Collision: \nNext", 2);
  986.  
  987.           count = 0;
  988.  
  989.           while (count < 10)
  990.           {
  991.             r_qti = get_qti(A0);
  992.             m_qti = get_qti(A1);
  993.             l_qti = get_qti(A2);
  994.  
  995.             getpos(l_qti, m_qti, r_qti, pos);
  996.             // count how many interceptions have been passed
  997.             if (l_qti > thre3 && m_qti > thre3 && r_qti > thre3) {
  998.  
  999.               count++;
  1000.             }
  1001.             else
  1002.             {
  1003.               linefollow(pos);
  1004.             }
  1005.           }
  1006.           forward();
  1007.           delay(250);
  1008.           if (carDirection == "N") {
  1009.             yCurrent++;
  1010.           } else if (carDirection == "S") {
  1011.             yCurrent--;
  1012.           } else if (carDirection == "E") {
  1013.             xCurrent++;
  1014.           } else if (carDirection == "W") {
  1015.             xCurrent--;
  1016.           }
  1017.         }
  1018.  
  1019.         Serial1.print("PUB|LF:");
  1020.         Serial1.print(xCurrent);
  1021.         Serial1.print(",");
  1022.         Serial1.print(yCurrent);
  1023.         Serial1.print(",");
  1024.         Serial1.println(carDirection);
  1025.       }
  1026.  
  1027.       //Line Following: Set Current Coordinate
  1028.       //Car 1
  1029.       else if (mqtt_msg.topic == "JARVIS/server/1/LF_C")
  1030.       //Car 2
  1031.       //else if (mqtt_msg.topic == "JARVIS/server/2/LF_C")
  1032.       {
  1033.         lineFollowingSetCurrentCoordinate(mqtt_msg.payload);
  1034.       }
  1035.  
  1036.       //Line Following: Change Coordinate
  1037.       //Car 1
  1038.       else if (mqtt_msg.topic == "JARVIS/server/1/LF" || mqtt_msg.topic == "JARVIS/server/LF")
  1039.         //Car 2
  1040.       //else if (mqtt_msg.topic == "JARVIS/server/2/LF" || mqtt_msg.topic == "JARVIS/server/LF")
  1041.       {
  1042.         lineFollowingChageCoordinate(mqtt_msg.payload);
  1043.       }
  1044.     }
  1045.   }
  1046.  
  1047.   if (mode == "D")
  1048.   {
  1049.     stay();
  1050.   }
  1051.   else if (mode == "LF")
  1052.   {
  1053.     lineFollowing();
  1054.     /*
  1055.       Serial1.print("PUB|LF:");
  1056.       Serial1.print(xCurrent);
  1057.       Serial1.print(",");
  1058.       Serial1.print(yCurrent);
  1059.       Serial1.print(",");
  1060.       Serial1.println(carDirection);
  1061.     */
  1062.   }
  1063.   else if (mode == "LT")
  1064.   {
  1065.     lightTracking();
  1066.   }
  1067.   else if (mode == "RED")
  1068.   {
  1069.     findingRedSpot();
  1070.   }
  1071. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement