Advertisement
Cpt_Jellyfish

EEEE4008: Object Manipulator Auxiliary Platform: Arduino UNO (Slave) Code

May 13th, 2021
591
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.32 KB | None | 0 0
  1. // *** Object Manipulator 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 servos
  14. Servo s1;
  15. Servo s2;
  16. Servo s3;
  17. Servo s4;
  18.  
  19. //define the stepper motor pin connections
  20. const int step1Pin = 8;
  21. const int dir1Pin = 7;
  22. const int step2Pin = 6;
  23. const int dir2Pin = 5;
  24. const int step3Pin = 4;
  25. const int dir3Pin = 3;
  26.  
  27. int s1Pos = 0;
  28. int s1PosNext = 0;
  29. int s2Pos = 0;
  30. int s2PosNext = 0;
  31. int s3Pos = 0;
  32. int s3PosNext = 0;
  33. int s4Pos = 0;
  34. int s4PosNext = 0;
  35.  
  36. bool toggleDrive;
  37.  
  38. //note these will both be empty and added to in code
  39. String extracted_route_str[] = {"U","80","R","30","U","30","R","30","U","50","R","20","D","10"};
  40. char extracted_route_char[] = {'U','80','R','30','U','30','R','30','U','50','R','20','D','10'};
  41. int routeLength = sizeof(extracted_route_char);
  42.  
  43. int pathDistance = 0;
  44.  
  45. int motor1Count = 0;
  46. int motor2Count = 0;
  47. int motor3Count = 0;
  48.  
  49. bool followedRoute = false;
  50.  
  51.  
  52. RF24 radio(9, 10);   // nRF24L01 (CE, CSN)
  53.  
  54. //configure the stepper motors
  55. AccelStepper motor1(1,step1Pin, dir1Pin); //1 is a driver interface
  56. AccelStepper motor2(1,step2Pin, dir2Pin);
  57. AccelStepper motor3(1,step3Pin, dir3Pin);
  58.  
  59. MultiStepper motors;
  60.  
  61. long positions[3];  
  62.  
  63. const byte address[6] = "00001"; //NRF24L01 address
  64.  
  65. //timer variables
  66. unsigned long lastReceiveTime = 0;
  67. unsigned long currentTime = 0;
  68.  
  69. //max size of this structure is 32 bytes - NRF24L01 buffer limit
  70. struct Data_Package {
  71.   byte jLValX;
  72.   byte jLValY;
  73.   byte jRValX;
  74.   byte jRValY;
  75.   byte toggleButton;
  76.   byte switchButton;
  77.   byte fireButton;
  78.   byte grabButton;
  79. };
  80.  
  81. Data_Package data; //create a variable with the above structure
  82.  
  83. //input matrix elements
  84. float a = cos((240*3.14159)/180);
  85. float b = cos((120*3.14159)/180);
  86. float c = cos(0);
  87. float d = sin((240*3.14159)/180);
  88. float e = sin((120*3.14159)/180);
  89. float f = sin(0);
  90. float g = 1;
  91. float h = 1;
  92. float i = 1;
  93.  
  94. //calculate determinant
  95. float det = (a*e*i)+(b*f*g)+(c*d*h)-(c*e*g)-(a*f*h)-(b*d*i);
  96.  
  97. //calculate inverse elements
  98. float a_inverse = ((e*i)-(f*h))/det;
  99. float b_inverse = ((h*c)-(i*b))/det;
  100. float c_inverse = ((b*f)-(c*e))/det;
  101. float d_inverse = ((g*f)-(d*i))/det;
  102. float e_inverse = ((a*i)-(g*c))/det;
  103. float f_inverse = ((d*c)-(a*f))/det;
  104. float g_inverse = ((d*h)-(g*e))/det;
  105. float h_inverse = ((g*b)-(a*h))/det;
  106. float i_inverse = ((a*e)-(d*b))/det;
  107.  
  108. //default normalised controller variables
  109. float jLValX_Normalised = 0;
  110. float jLValY_Normalised = 0;
  111. float jRValX_Normalised = 0;
  112.  
  113. //default motor speeds (set to OFF)
  114. float motor1Speed = 0;
  115. float motor2Speed = 0;
  116. float motor3Speed = 0;
  117.  
  118. received = false;
  119.  
  120. void receiveEvent(long x) {
  121.   while (Wire.available()) { // loop through all but the last
  122.     extracted_route_str[] = x;
  123.     extracted_route_char[] = x;
  124.     received = true;
  125.  
  126.     //uncomment for I2C transmission back to Raspberry Pi
  127.     //Wire.beginTransmission(4);
  128.     //Wire.write(route);
  129.     //Wire.endTransmission();
  130.   }
  131. }
  132.  
  133. void setup() {
  134.   Serial.begin(9600); //serial monitor channel
  135.  
  136.   //I2C setup
  137.   Wire.begin(0x8);
  138.   Wire.onReceive(receiveEvent);
  139.  
  140.   //servo pin assignment
  141.   s1.attach(5);
  142.   s2.attach(6);
  143.   s3.attach(7);
  144.   s4.attach(8);
  145.  
  146.   //setup the NRF24L01 module
  147.   pinMode(9, OUTPUT);
  148.   radio.begin();
  149.   radio.openReadingPipe(0, address);
  150.   radio.setAutoAck(false);
  151.   radio.setDataRate(RF24_250KBPS);
  152.   radio.setPALevel(RF24_PA_LOW);
  153.   radio.startListening(); //set the module as receiver
  154.   resetData(); //refresh data
  155.  
  156.   toggleDrive = true;
  157.  
  158.   //configure motor max speed and acceleration
  159.   motor1.setMaxSpeed(5000);
  160.   motor2.setMaxSpeed(5000);
  161.   motor3.setMaxSpeed(5000);
  162.   motor1.setAcceleration(1000);
  163.   motor2.setAcceleration(1000);
  164.   motor3.setAcceleration(1000);
  165.   motor1.setSpeed(0);
  166.   motor2.setSpeed(0);
  167.   motor3.setSpeed(0);
  168.  
  169.   motors.addStepper(motor1);
  170.   motors.addStepper(motor2);
  171.   motors.addStepper(motor3);
  172. }
  173.  
  174. void loop() {
  175.   if (!followedRoute && received){
  176.     for (int i = 0; i < routeLength; i++){    
  177.       if (extracted_route_char[i] == 'U' || extracted_route_char[i] == 'D' || extracted_route_char[i] == 'L' || extracted_route_char[i] == 'R'){
  178.         String tmp = extracted_route_str[i+1];
  179.         pathDistance = tmp.toInt();
  180.         char dir = extracted_route_char[i];
  181.         switch (dir) {
  182.           case 'U':
  183.             translateUp(pathDistance);
  184.             break;
  185.           case 'D':
  186.             translateDown(pathDistance);
  187.             break;
  188.           case 'L':
  189.             translateLeft(pathDistance);
  190.             break;
  191.           case 'R':
  192.             translateRight(pathDistance);
  193.             break;
  194.         }
  195.       }
  196.       else {
  197.         //nothing
  198.       }
  199.     }
  200.     followedRoute = true;
  201.   }
  202.  
  203.   else if (received){
  204.  
  205.     readData();
  206.     delay(100);
  207.  
  208.     if (data.toggleButton == 0){
  209.       toggleDrive = !toggleDrive;
  210.     }
  211.    
  212.     if (toggleDrive == true) {
  213.       Serial.println("Drive Mode");
  214.      
  215.       readData();
  216.       delay(100);
  217.       if (data.toggleButton == 0){
  218.         toggleDrive = !toggleDrive;
  219.       }
  220.  
  221.       //insert drive code
  222.       convertJoystickVal();
  223.       //run the motors at the calculated speed
  224.       motor1.runSpeed();
  225.       motor2.runSpeed();
  226.       motor3.runSpeed();
  227.     }
  228.  
  229.     else {
  230.       //object manipulator code
  231.       Serial.println("Functionality Mode");
  232.      
  233.       s1Pos = s1.read();
  234.       s2Pos = s2.read();
  235.       s3Pos = s3.read();
  236.       s4Pos = s4.read();
  237.    
  238.       // elbow - joint 1 - base
  239.       if (data.jLValX >= 150) {
  240.         //move CC
  241.         if (s1Pos > 50){
  242.           s1PosNext = s1Pos - 1;
  243.           s1.write(s1PosNext);
  244.         }
  245.         else {
  246.         }
  247.       }
  248.    
  249.       if (data.jLValX < 100) {
  250.         //move C
  251.         if (s1Pos <= 170){
  252.           s1PosNext = s1Pos + 1;
  253.           s1.write(s1PosNext);
  254.         }
  255.         else {
  256.         }
  257.       }
  258.    
  259.       // elbow - joint 2 - middle
  260.       if (data.jLValY >= 150) {
  261.         //move CC
  262.         if (s2Pos > 90){
  263.           s2PosNext = s2Pos - 1;
  264.           s2.write(s2PosNext);
  265.         }
  266.         else {
  267.         }
  268.       }
  269.    
  270.       if (data.jLValY < 100) {
  271.         //move C
  272.         if (s2Pos <= 170){
  273.           s2PosNext = s2Pos + 1;
  274.           s2.write(s2PosNext);
  275.         }
  276.         else {
  277.         }
  278.       }
  279.    
  280.       // wrist - joint 3 - top
  281.       if (data.jRValX >= 150) {
  282.         //move CC
  283.         if (s3Pos > 10){
  284.           s3PosNext = s3Pos - 1;
  285.           s3.write(s3PosNext);
  286.         }
  287.         else {
  288.         }
  289.       }
  290.    
  291.       if (data.jRValX < 100) {
  292.         //move C
  293.         if (s3Pos <= 170){
  294.           s3PosNext = s3Pos + 1;
  295.           s3.write(s3PosNext);
  296.         }
  297.         else {
  298.         }
  299.       }
  300.    
  301.       // grabber
  302.       if (data.jRValY >= 150) {
  303.         //move CC
  304.         if (s4Pos < 105){
  305.           s4PosNext = s4Pos + 1;
  306.           s4.write(s4PosNext);
  307.         }
  308.         else {
  309.         }
  310.       }
  311.    
  312.       if (data.jRValY < 100) {
  313.         //move C
  314.         if (s4Pos > 20){
  315.           s4PosNext = s4Pos - 1;
  316.           s4.write(s4PosNext);
  317.         }
  318.         else {
  319.         }
  320.       }
  321.     }
  322.    
  323.     /*Serial.print(data.jLValX);
  324.     Serial.print(":");
  325.     Serial.print(data.jLValY);
  326.     Serial.print(":");
  327.     Serial.print(data.jRValX);
  328.     Serial.print(":");
  329.     Serial.println(data.jRValY);*/
  330.   }
  331. }
  332.  
  333. void resetData() {
  334.   //reset the values when there is no radio connection - set initial default values
  335.   data.jLValX = 127; //map value from 0-1023 to 0-255 (byte)
  336.   data.jLValY = 127;
  337.   data.jRValX = 127;
  338.   data.jRValY = 127;
  339.   data.toggleButton = 1; //connected to GND so 0 when pressed
  340.   data.switchButton = 1;
  341.   data.fireButton = 1;
  342.   data.grabButton = 1;
  343. }
  344.  
  345. void readData() {
  346.       // Check whether there is data to be received
  347.   if (radio.available()) {
  348.     radio.read(&data, sizeof(Data_Package)); // Read the whole data and store it into the 'data' structure
  349.     lastReceiveTime = millis(); // At this moment we have received the data
  350.   }
  351.   // Check whether we keep receving data, or we have a connection between the two modules
  352.   currentTime = millis();
  353.   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
  354.     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
  355.   }
  356. }
  357.  
  358. void convertJoystickVal(){
  359.   //check whether there is data to be received
  360.   if (radio.available()) {
  361.     radio.read(&data, sizeof(Data_Package)); //read the whole data and store it into the 'data' structure
  362.     lastReceiveTime = millis(); //at this moment the data is received
  363.   }
  364.   //check whether to keep receving data or if there is a connection between the two modules
  365.   currentTime = millis();
  366.   if ( currentTime - lastReceiveTime > 1000 ) { //if the current time is >1 second since the last data was recived then connection is lost
  367.     resetData(); //if connection is lost then reset the data - prevents unwanted behavior
  368.   }
  369.  
  370.   //left joystick x axis conversion
  371.   jLValX_Normalised = map(data.jLValX, 255, 0, 127, -127); //map(minInput, maxInput, minOutput, maxOutput)
  372.   if ((jLValX_Normalised < 5) && (jLValX_Normalised > -5)){
  373.     jLValX_Normalised = 0;
  374.   }
  375.  
  376.   //left joystick y axis conversion
  377.   jLValY_Normalised = map(data.jLValY, 255, 0, -127, 127);
  378.   if ((jLValY_Normalised < 5) && (jLValY_Normalised > -5)){
  379.     jLValY_Normalised = 0;
  380.   }
  381.  
  382.   //right joystick conversion
  383.   jRValX_Normalised = map(data.jRValX, 0, 255, 127, -127);
  384.   if ((jRValX_Normalised < 5) && (jRValX_Normalised > -5)){
  385.     jRValX_Normalised = 0;
  386.   }
  387.  
  388.   //calculate motor speeds
  389.   motor1Speed = ((a_inverse*jLValX_Normalised)+(b_inverse*jLValY_Normalised)+(c_inverse*jRValX_Normalised))*5;
  390.   motor2Speed = ((d_inverse*jLValX_Normalised)+(e_inverse*jLValY_Normalised)+(f_inverse*jRValX_Normalised))*5;
  391.   motor3Speed = ((g_inverse*jLValX_Normalised)+(h_inverse*jLValY_Normalised)+(i_inverse*jRValX_Normalised))*5;
  392.  
  393.   /*
  394.   Serial.print("M1: ");
  395.   Serial.println(motor1Speed);
  396.   Serial.print("M2: ");
  397.   Serial.println(motor2Speed);
  398.   Serial.print("M3: ");
  399.   Serial.println(motor3Speed);
  400.   */
  401.  
  402.   //run motors at the calculated speed
  403.   motor1.setSpeed(motor1Speed);
  404.   motor2.setSpeed(motor2Speed);
  405.   motor3.setSpeed(motor3Speed);
  406. }
  407.  
  408. void translateUp(int pathDistance){
  409.   positions[0] = int(-1.1547*pathDistance);
  410.   positions[1] = int(1.1547*pathDistance);
  411.   positions[2] = 0;
  412.   Serial.print("Up: ");
  413.   Serial.print(positions[0]);
  414.   Serial.print(", ");
  415.   Serial.print(positions[1]);
  416.   Serial.print(",");
  417.   Serial.println(positions[2]);
  418.   motor1.setCurrentPosition(0);
  419.   motor2.setCurrentPosition(0);
  420.   motor3.setCurrentPosition(0);
  421.   motors.moveTo(positions);
  422. }
  423.  
  424. void translateDown(int pathDistance){
  425.   positions[0] = int(1.1547*pathDistance);
  426.   positions[1] = int(-1.1547*pathDistance);
  427.   positions[2] = 0;
  428.   Serial.print("Down: ");
  429.   Serial.print(positions[0]);
  430.   Serial.print(", ");
  431.   Serial.print(positions[1]);
  432.   Serial.print(",");
  433.   Serial.println(positions[2]);
  434.   motor1.setCurrentPosition(0);
  435.   motor2.setCurrentPosition(0);
  436.   motor3.setCurrentPosition(0);
  437.   motors.moveTo(positions);
  438. }
  439.  
  440. void translateLeft(int pathDistance){
  441.   positions[0] = int(pathDistance/2);
  442.   positions[1] = int(pathDistance/2);
  443.   positions[2] = -(pathDistance);
  444.   Serial.print("Left: ");
  445.   Serial.print(positions[0]);
  446.   Serial.print(", ");
  447.   Serial.print(positions[1]);
  448.   Serial.print(",");
  449.   Serial.println(positions[2]);
  450.   motor1.setCurrentPosition(0);
  451.   motor2.setCurrentPosition(0);
  452.   motor3.setCurrentPosition(0);
  453.   motors.moveTo(positions);
  454. }
  455.  
  456. void translateRight(int pathDistance){
  457.   positions[0] = int(-pathDistance/2);
  458.   positions[1] = int(-pathDistance/2);
  459.   positions[2] = pathDistance;
  460.   Serial.print("Right: ");
  461.   Serial.print(positions[0]);
  462.   Serial.print(", ");
  463.   Serial.print(positions[1]);
  464.   Serial.print(",");
  465.   Serial.println(positions[2]);
  466.   motor1.setCurrentPosition(0);
  467.   motor2.setCurrentPosition(0);
  468.   motor3.setCurrentPosition(0);
  469.   motors.moveTo(positions);
  470. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement