Cpt_Jellyfish

EEEE4008: Projectile Shooter Auxiliary Platform: Arduino UNO (Slave) Code

May 13th, 2021 (edited)
557
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.57 KB | None | 0 0
  1. // *** Projectile Shooter Tri-Omniwheel Robot with Variable Controller Translation & Rotation Inputs
  2. // *** Including Switch & Route Following Code Segments
  3.  
  4. //include libraries
  5. #include <SPI.h>
  6. #include <Wire.h>
  7. #include <nRF24L01.h>
  8. #include <RF24.h>
  9. #include <AccelStepper.h>
  10. #include <MultiStepper.h>
  11. #include <Servo.h>
  12.  
  13. //initialise servo
  14. Servo s1;
  15.  
  16. //define the stepper motor pin connections
  17. const int step1Pin = 8;
  18. const int dir1Pin = 7;
  19. const int step2Pin = 6;
  20. const int dir2Pin = 5;
  21. const int step3Pin = 4;
  22. const int dir3Pin = 3;
  23.  
  24. int s1Pos = 0;
  25.  
  26. bool toggleSpinners;
  27. bool toggleFire;
  28.  
  29. //note these will both be empty and added to in code
  30. String extracted_route_str[] = {"U","80","R","30","U","30","R","30","U","50","R","20","D","10"};
  31. char extracted_route_char[] = {'U','80','R','30','U','30','R','30','U','50','R','20','D','10'};
  32. int routeLength = sizeof(extracted_route_char);
  33.  
  34. int pathDistance = 0;
  35.  
  36. int motor1Count = 0;
  37. int motor2Count = 0;
  38. int motor3Count = 0;
  39.  
  40. bool followedRoute = false;
  41.  
  42.  
  43. RF24 radio(9, 10);   // nRF24L01 (CE, CSN)
  44.  
  45. //configure the stepper motors
  46. AccelStepper motor1(1,step1Pin, dir1Pin); //1 is a driver interface
  47. AccelStepper motor2(1,step2Pin, dir2Pin);
  48. AccelStepper motor3(1,step3Pin, dir3Pin);
  49.  
  50. MultiStepper motors;
  51.  
  52. long positions[3];  
  53.  
  54. const byte address[6] = "00001"; //NRF24L01 address
  55.  
  56. //timer variables
  57. unsigned long lastReceiveTime = 0;
  58. unsigned long currentTime = 0;
  59.  
  60. //max size of this structure is 32 bytes - NRF24L01 buffer limit
  61. struct Data_Package {
  62.   byte jLValX;
  63.   byte jLValY;
  64.   byte jRValX;
  65.   byte jRValY;
  66.   byte toggleButton;
  67.   byte switchButton;
  68.   byte fireButton;
  69.   byte grabButton;
  70. };
  71.  
  72. Data_Package data; //create a variable with the above structure
  73.  
  74. //input matrix elements
  75. float a = cos((240*3.14159)/180);
  76. float b = cos((120*3.14159)/180);
  77. float c = cos(0);
  78. float d = sin((240*3.14159)/180);
  79. float e = sin((120*3.14159)/180);
  80. float f = sin(0);
  81. float g = 1;
  82. float h = 1;
  83. float i = 1;
  84.  
  85. //calculate determinant
  86. float det = (a*e*i)+(b*f*g)+(c*d*h)-(c*e*g)-(a*f*h)-(b*d*i);
  87.  
  88. //calculate inverse elements
  89. float a_inverse = ((e*i)-(f*h))/det;
  90. float b_inverse = ((h*c)-(i*b))/det;
  91. float c_inverse = ((b*f)-(c*e))/det;
  92. float d_inverse = ((g*f)-(d*i))/det;
  93. float e_inverse = ((a*i)-(g*c))/det;
  94. float f_inverse = ((d*c)-(a*f))/det;
  95. float g_inverse = ((d*h)-(g*e))/det;
  96. float h_inverse = ((g*b)-(a*h))/det;
  97. float i_inverse = ((a*e)-(d*b))/det;
  98.  
  99. //default normalised controller variables
  100. float jLValX_Normalised = 0;
  101. float jLValY_Normalised = 0;
  102. float jRValX_Normalised = 0;
  103.  
  104. //default motor speeds (set to OFF)
  105. float motor1Speed = 0;
  106. float motor2Speed = 0;
  107. float motor3Speed = 0;
  108.  
  109. bool received = false;
  110.  
  111. void receiveEvent(long x) {
  112.   while (Wire.available()) { // loop through all but the last
  113.     extracted_route_str[] = x;
  114.     extracted_route_char[] = x;
  115.     received = true;
  116.  
  117.     //uncomment for I2C transmission back to Raspberry Pi
  118.     //Wire.beginTransmission(4);
  119.     //Wire.write(route);
  120.     //Wire.endTransmission();
  121.   }
  122. }
  123.  
  124. void setup() {
  125.   Serial.begin(9600); //serial monitor channel
  126.  
  127.   //I2C setup
  128.   Wire.begin(0x8);
  129.   Wire.onReceive(receiveEvent);
  130.  
  131.   s1.attach(5);
  132.  
  133.   //setup the NRF24L01 module
  134.   pinMode(9, OUTPUT);
  135.   radio.begin();
  136.   radio.openReadingPipe(0, address);
  137.   radio.setAutoAck(false);
  138.   radio.setDataRate(RF24_250KBPS);
  139.   radio.setPALevel(RF24_PA_LOW);
  140.   radio.startListening(); //set the module as receiver
  141.   resetData(); //refresh data
  142.  
  143.   toggleDrive = true;
  144.  
  145.   //configure motor max speed and acceleration
  146.   motor1.setMaxSpeed(5000);
  147.   motor2.setMaxSpeed(5000);
  148.   motor3.setMaxSpeed(5000);
  149.   motor1.setAcceleration(1000);
  150.   motor2.setAcceleration(1000);
  151.   motor3.setAcceleration(1000);
  152.   motor1.setSpeed(0);
  153.   motor2.setSpeed(0);
  154.   motor3.setSpeed(0);
  155.  
  156.   motors.addStepper(motor1);
  157.   motors.addStepper(motor2);
  158.   motors.addStepper(motor3);
  159. }
  160.  
  161. void loop() {
  162.   if (!followedRoute && received){
  163.     for (int i = 0; i < routeLength; i++){    
  164.       if (extracted_route_char[i] == 'U' || extracted_route_char[i] == 'D' || extracted_route_char[i] == 'L' || extracted_route_char[i] == 'R'){
  165.         String tmp = extracted_route_str[i+1];
  166.         pathDistance = tmp.toInt();
  167.         char dir = extracted_route_char[i];
  168.         switch (dir) {
  169.           case 'U':
  170.             translateUp(pathDistance);
  171.             break;
  172.           case 'D':
  173.             translateDown(pathDistance);
  174.             break;
  175.           case 'L':
  176.             translateLeft(pathDistance);
  177.             break;
  178.           case 'R':
  179.             translateRight(pathDistance);
  180.             break;
  181.         }
  182.       }
  183.       else {
  184.         //nothing
  185.       }
  186.     }
  187.     followedRoute = true;
  188.   }
  189.  
  190.   else if (received){
  191.  
  192.     readData();
  193.     delay(100);
  194.  
  195.     if (data.toggleButton == 0){
  196.       toggleSpinners = !toggleSpinners;
  197.     }
  198.  
  199.     if (data.fireButton == 0){
  200.       toggleFire = true;
  201.     }
  202.    
  203.     if (toggleSpinners == true) {
  204.       Serial.println("Spinners On");
  205.       digitalWrite(2, HIGH);
  206.     }
  207.     else {
  208.       digitalWrite(2, LOW);
  209.     }
  210.  
  211.     if ((toggleFire == true) and (toggleSpinners == true)){
  212.       Serial.println("Fire");
  213.       delay(100);
  214.       s1.write(90); //move to open position
  215.       delay(200);
  216.       s1.write(0); //move to closed position
  217.       toggleFire = false;
  218.     }
  219.     else {
  220.       toggleFire = false;
  221.     }
  222.    
  223.     //insert drive code
  224.     convertJoystickVal();
  225.     //run the motors at the calculated speed
  226.     motor1.runSpeed();
  227.     motor2.runSpeed();
  228.     motor3.runSpeed();
  229.    
  230.     /*Serial.print(data.jLValX);
  231.     Serial.print(":");
  232.     Serial.print(data.jLValY);
  233.     Serial.print(":");
  234.     Serial.print(data.jRValX);
  235.     Serial.print(":");
  236.     Serial.println(data.jRValY);*/
  237.   }
  238. }
  239.  
  240. void resetData() {
  241.   //reset the values when there is no radio connection - set initial default values
  242.   data.jLValX = 127; //map value from 0-1023 to 0-255 (byte)
  243.   data.jLValY = 127;
  244.   data.jRValX = 127;
  245.   data.jRValY = 127;
  246.   data.toggleButton = 1; //connected to GND so 0 when pressed
  247.   data.switchButton = 1;
  248.   data.fireButton = 1;
  249.   data.grabButton = 1;
  250. }
  251.  
  252. void readData() {
  253.       // Check whether there is data to be received
  254.   if (radio.available()) {
  255.     radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure
  256.     lastReceiveTime = millis(); // At this moment we have received the data
  257.   }
  258.   // Check whether we keep receving data, or we have a connection between the two modules
  259.   currentTime = millis();
  260.   if ( currentTime - lastReceiveTime > 1000 ) { // If current time is more then 1 second since we have recived the last data, that means we have lost connection
  261.     resetData(); // If connection is lost, reset the data. It prevents unwanted behavior, for example if a drone has a throttle up and we lose connection, it can keep flying unless we reset the values
  262.   }
  263. }
  264.  
  265. void convertJoystickVal(){
  266.   //check whether there is data to be received
  267.   if (radio.available()) {
  268.     radio.read(&data, sizeof(Data_Package)); //read the whole data and store it into the 'data' structure
  269.     lastReceiveTime = millis(); //at this moment the data is received
  270.   }
  271.   //check whether to keep receving data or if there is a connection between the two modules
  272.   currentTime = millis();
  273.   if ( currentTime - lastReceiveTime > 1000 ) { //if the current time is >1 second since the last data was recived then connection is lost
  274.     resetData(); //if connection is lost then reset the data - prevents unwanted behavior
  275.   }
  276.  
  277.   //left joystick x axis conversion
  278.   jLValX_Normalised = map(data.jLValX, 255, 0, 127, -127); //map(minInput, maxInput, minOutput, maxOutput)
  279.   if ((jLValX_Normalised < 5) && (jLValX_Normalised > -5)){
  280.     jLValX_Normalised = 0;
  281.   }
  282.  
  283.   //left joystick y axis conversion
  284.   jLValY_Normalised = map(data.jLValY, 255, 0, -127, 127);
  285.   if ((jLValY_Normalised < 5) && (jLValY_Normalised > -5)){
  286.     jLValY_Normalised = 0;
  287.   }
  288.  
  289.   //right joystick conversion
  290.   jRValX_Normalised = map(data.jRValX, 0, 255, 127, -127);
  291.   if ((jRValX_Normalised < 5) && (jRValX_Normalised > -5)){
  292.     jRValX_Normalised = 0;
  293.   }
  294.  
  295.   //calculate motor speeds
  296.   motor1Speed = ((a_inverse*jLValX_Normalised)+(b_inverse*jLValY_Normalised)+(c_inverse*jRValX_Normalised))*5;
  297.   motor2Speed = ((d_inverse*jLValX_Normalised)+(e_inverse*jLValY_Normalised)+(f_inverse*jRValX_Normalised))*5;
  298.   motor3Speed = ((g_inverse*jLValX_Normalised)+(h_inverse*jLValY_Normalised)+(i_inverse*jRValX_Normalised))*5;
  299.  
  300.   /*
  301.   Serial.print("M1: ");
  302.   Serial.println(motor1Speed);
  303.   Serial.print("M2: ");
  304.   Serial.println(motor2Speed);
  305.   Serial.print("M3: ");
  306.   Serial.println(motor3Speed);
  307.   */
  308.  
  309.   //run motors at the calculated speed
  310.   motor1.setSpeed(motor1Speed);
  311.   motor2.setSpeed(motor2Speed);
  312.   motor3.setSpeed(motor3Speed);
  313. }
  314.  
  315. void translateUp(int pathDistance){
  316.   positions[0] = int(-1.1547*pathDistance);
  317.   positions[1] = int(1.1547*pathDistance);
  318.   positions[2] = 0;
  319.   Serial.print("Up: ");
  320.   Serial.print(positions[0]);
  321.   Serial.print(", ");
  322.   Serial.print(positions[1]);
  323.   Serial.print(",");
  324.   Serial.println(positions[2]);
  325.   motor1.setCurrentPosition(0);
  326.   motor2.setCurrentPosition(0);
  327.   motor3.setCurrentPosition(0);
  328.   motors.moveTo(positions);
  329. }
  330.  
  331. void translateDown(int pathDistance){
  332.   positions[0] = int(1.1547*pathDistance);
  333.   positions[1] = int(-1.1547*pathDistance);
  334.   positions[2] = 0;
  335.   Serial.print("Down: ");
  336.   Serial.print(positions[0]);
  337.   Serial.print(", ");
  338.   Serial.print(positions[1]);
  339.   Serial.print(",");
  340.   Serial.println(positions[2]);
  341.   motor1.setCurrentPosition(0);
  342.   motor2.setCurrentPosition(0);
  343.   motor3.setCurrentPosition(0);
  344.   motors.moveTo(positions);
  345. }
  346.  
  347. void translateLeft(int pathDistance){
  348.   positions[0] = int(pathDistance/2);
  349.   positions[1] = int(pathDistance/2);
  350.   positions[2] = -(pathDistance);
  351.   Serial.print("Left: ");
  352.   Serial.print(positions[0]);
  353.   Serial.print(", ");
  354.   Serial.print(positions[1]);
  355.   Serial.print(",");
  356.   Serial.println(positions[2]);
  357.   motor1.setCurrentPosition(0);
  358.   motor2.setCurrentPosition(0);
  359.   motor3.setCurrentPosition(0);
  360.   motors.moveTo(positions);
  361. }
  362.  
  363. void translateRight(int pathDistance){
  364.   positions[0] = int(-pathDistance/2);
  365.   positions[1] = int(-pathDistance/2);
  366.   positions[2] = pathDistance;
  367.   Serial.print("Right: ");
  368.   Serial.print(positions[0]);
  369.   Serial.print(", ");
  370.   Serial.print(positions[1]);
  371.   Serial.print(",");
  372.   Serial.println(positions[2]);
  373.   motor1.setCurrentPosition(0);
  374.   motor2.setCurrentPosition(0);
  375.   motor3.setCurrentPosition(0);
  376.   motors.moveTo(positions);
  377. }
Add Comment
Please, Sign In to add comment