Advertisement
Guest User

Untitled

a guest
Nov 7th, 2015
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.34 KB | None | 0 0
  1.  
  2. #include <avr/wdt.h> //library to use watchdog timers for AVR chips
  3.  
  4. /*
  5. Motor pins in order:
  6. Motor 1 PWM
  7. Motor 2 PWM
  8. Motor 3 PWM
  9. Motor 4 PWM
  10. Motor 1 direction
  11. Motor 2 direction
  12. Motor 3 direction
  13. Motro 4 direction
  14.  
  15. PWM = pulse width modulation, used to control speed
  16. direction = CW or CCW rotation of the motors
  17. */
  18. #define    M1_PWM                46
  19. #define    M2_PWM                 9
  20. #define    M3_PWM                44
  21. #define    M4_PWM                 3
  22. #define    M1_DIR                 7
  23. #define    M2_DIR                 2
  24. #define    M3_DIR                 8
  25. #define    M4_DIR                10
  26.  
  27. /*
  28. Pins for the HC-SR04 ultrasonic sensor
  29. Trigger pin to send out a ultrasonic pulse.
  30. Echo pin to listen for the pulse echo.
  31. */
  32. #define    SONAR_TRIG             6
  33. #define    SONAR_ECHO             5
  34.  
  35. /*
  36. Encoder input pins used to trigger encoder count interrupts.
  37. */
  38. #define    ENCODER_1_A              22
  39. #define    ENCODER_1_B              23
  40. #define    ENCODER_2_A             24
  41. #define    ENCODER_2_B              25
  42. #define    ENCODER_3_A             26
  43. #define    ENCODER_3_B              27
  44. #define    ENCODER_4_A             28
  45. #define    ENCODER_4_B              29
  46. #define    ENCODER_INT_1          21
  47. #define    ENCODER_INT_2          20
  48. #define    ENCODER_INT_3           19
  49. #define    ENCODER_INT_4           18
  50.  
  51. /*
  52. Command characters and event characters:
  53. d = request to use drive function.
  54. p = request to use ping function
  55. h = request to use halt function
  56. t = request to use turn function
  57. e = request encoder count
  58. x = error event occurred
  59. b = heartbeat signal character
  60. \r = terminating character for packet data
  61. */
  62. const char     DRIVE_CODE    =    'd';
  63. const char     PING_CODE     =    'p';
  64. const char     HALT_CODE     =    'h';
  65. const char     TURN_CODE     =    't';
  66. const char     ENC_CODE      =    'e';
  67. const char     ERR_CODE      =    'x';
  68. const char     HTBT_CODE     =    'b';
  69. const char     TERMINATOR    =    '\r';
  70.  
  71. /*
  72. Encoder count variable. This count can go negative.
  73. */
  74. volatile long  count1 = 0;
  75. volatile long  count2 = 0;
  76. volatile long  count3 = 0;
  77. volatile long  count4 = 0;
  78.  
  79. volatile unsigned char new1;
  80. volatile unsigned char old1;
  81. volatile unsigned char new2;
  82. volatile unsigned char old2;
  83. volatile unsigned char new3;
  84. volatile unsigned char old3;
  85. volatile unsigned char new4;
  86. volatile unsigned char old4;
  87.  
  88. // Quadrature Encoder Matrix
  89. int QEM [16] = {0,-1,1,2,1,0,2,-1,-1,2,0,1,2,1,-1,0};              
  90.  
  91. int j = 0;
  92.  
  93. double tol = 1.0;
  94.  
  95. void setup()
  96. {
  97.     interrupts();
  98.   Serial.begin(19200);  //start UART0 with a baud of 19200 Bps
  99.   //wdt_enable (WDTO_8S); //enable the watchdog timer at 8S countdown
  100.  
  101.   /*
  102.   Set the drive mode of all of the motor pins to output.
  103.   Motors do not have any feedback so no input pin is needed
  104.   */
  105.   pinMode(M1_DIR, OUTPUT);
  106.   pinMode(M2_DIR, OUTPUT);
  107.   pinMode(M3_DIR, OUTPUT);
  108.   pinMode(M4_DIR, OUTPUT);
  109.   pinMode(M1_PWM, OUTPUT);
  110.   pinMode(M2_PWM, OUTPUT);
  111.   pinMode(M3_PWM, OUTPUT);
  112.   pinMode(M4_PWM, OUTPUT);
  113.  
  114.   pinMode(ENCODER_1_A, INPUT);
  115.   pinMode(ENCODER_1_B, INPUT);
  116.   pinMode(ENCODER_2_A, INPUT);
  117.   pinMode(ENCODER_2_B, INPUT);
  118.   pinMode(ENCODER_3_A, INPUT);
  119.   pinMode(ENCODER_3_B, INPUT);
  120.   pinMode(ENCODER_4_A, INPUT);
  121.   pinMode(ENCODER_4_B, INPUT);
  122.   pinMode(ENCODER_INT_1, INPUT);
  123.   pinMode(ENCODER_INT_2, INPUT);
  124.   pinMode(ENCODER_INT_3, INPUT);
  125.   pinMode(ENCODER_INT_4, INPUT);
  126.  
  127.   /*
  128.   Set the drive mode for the ultrasonic sensor.
  129.   Trigger is used to create a pulse, so must be an output.
  130.   Echo is used to sense a response so it must be input.
  131.   */
  132.   pinMode(SONAR_TRIG, OUTPUT);
  133.   pinMode(SONAR_ECHO, INPUT);
  134.  
  135.  
  136.   attachInterrupt(2, ecount1, CHANGE);
  137.   attachInterrupt(3, ecount2, CHANGE);
  138.   attachInterrupt(4, ecount3, CHANGE);
  139.   attachInterrupt(5, ecount4, CHANGE);
  140.  
  141.   /*
  142.   Initialize all of the motors to 0 (ie. off)
  143.   */
  144.   analogWrite(M1_PWM, 0);
  145.   analogWrite(M2_PWM, 0);
  146.   analogWrite(M3_PWM, 0);
  147.   analogWrite(M4_PWM, 0);
  148.  
  149.   /*
  150.   Set pin 13 to output. This pin is attached to a built in LED on teh arduino.
  151.   This LED will turn on to indicate that the program is now running
  152.   */
  153.   pinMode(13, OUTPUT);
  154.   digitalWrite(13, HIGH);
  155.   //Serial.println("Ready!");
  156. }
  157.  
  158. void loop()
  159. {
  160.     char command = 0; //char to hold command byte
  161.    
  162.     //if a byte is waiting in the serial buffer
  163.     if(Serial.available() > 0)
  164.     {
  165.         //wdt_reset(); //reset the watchdog timer (prevents shutdown!)
  166.         command = Serial.read(); //read the byte and store it.
  167.     }
  168.        
  169.     char data[8]; //data packet
  170.     int spd;
  171.     int rate;
  172.    
  173.    
  174.     if(dist() < (10.0 + tol) || dist() < (10.0 - tol))
  175.      {
  176.         analogWrite(M1_PWM, 0);
  177.         analogWrite(M2_PWM, 0);
  178.         analogWrite(M3_PWM, 0);
  179.         analogWrite(M4_PWM, 0);
  180.      }
  181.      
  182.     /*
  183.     Determines the appropriate function to use based on packet data.
  184.     Typical packet is as follows:
  185.     [command][param]...[param][terminator]
  186.     no spaces, no capitals.
  187.     ex:
  188.     To drive forward at 120 speed
  189.     "df120\r"
  190.    
  191.     all packets should be strings.
  192.     */
  193.     switch(command)
  194.     {
  195.         case DRIVE_CODE: //drive request made
  196.         {
  197.             /*
  198.             Read an 8 byte packet. 8 bytes not really needed, just gives extra padding
  199.             to ensure terminator '\r' is received. If terminator is received then
  200.             only bytes up to the terminator are read and the terminator is thrown away
  201.             */
  202.             Serial.readBytesUntil(TERMINATOR, data, 8);
  203.             spd = atoi(&data[1]); //convert lower bytes to int and store in spd
  204.             drive(spd, data[0]); //transfer to drive function
  205.             break;
  206.         }
  207.         case HALT_CODE: //halt request made
  208.             halt();
  209.             break;
  210.         case TURN_CODE: //turn request made
  211.         {
  212.             Serial.readBytesUntil(TERMINATOR, data, 8);
  213.             rate = atoi(&data[1]);
  214.             turn(rate, data[0]);
  215.             break;
  216.         }
  217.         case PING_CODE: //ping request made
  218.             ping();
  219.             break;
  220. //        case ENC_CODE: //count request made
  221. //            encoder_request();
  222. //            break;
  223.         //case HTBT_CODE: //heartbeat received
  224.           //  Serial.println("I am still alive");
  225.            // break;
  226.         case 0: //special cases. if nothing in the buffer 0 is constantly read.
  227.         case TERMINATOR: //some commands do not handle terminator '\r' leaving it in buffer
  228.             //in either of these events we do not want to throw an error, merely toss out the command.
  229.             break;
  230.         default: //an invalid command received or problem in transmission.
  231.             Serial.write(ERR_CODE); //reply with error event character
  232.             break;
  233.     }
  234.    
  235.     Serial.print("count1: ");
  236.     Serial.print(count1);
  237.     Serial.print("\tcount2: ");
  238.     Serial.print(count2);
  239.     Serial.print("\tcount3: ");
  240.     Serial.print(count3);
  241.     Serial.print("\tcount4: ");
  242.     Serial.println(count4);
  243.    
  244.     Serial.flush(); //clear the buffer
  245. }
  246.  
  247. /*
  248. Initiates forward or backward movement of the rover.
  249. spd = speed between 0 and 255
  250. dir = direction f = forward, b = backward
  251. */
  252. void drive(int spd, char dir)
  253. {
  254.     Serial.println("drive ack"); //acknowledge the command
  255.     if(dir == 'f')
  256.     {
  257.           analogWrite(M1_PWM, spd);
  258.           digitalWrite(M1_DIR, 1);
  259.           analogWrite(M2_PWM, spd);
  260.           digitalWrite(M2_DIR, 0);
  261.           analogWrite(M3_PWM, spd);
  262.           digitalWrite(M3_DIR, 1);
  263.           analogWrite(M4_PWM, spd);
  264.           digitalWrite(M4_DIR, 0);
  265.     }
  266.     else if(dir == 'b')
  267.     {
  268.           analogWrite(M1_PWM, spd);
  269.           digitalWrite(M1_DIR, 0);
  270.           analogWrite(M2_PWM, spd);
  271.           digitalWrite(M2_DIR, 1);
  272.           analogWrite(M3_PWM, spd);
  273.           digitalWrite(M3_DIR, 0);
  274.           analogWrite(M4_PWM, spd);
  275.           digitalWrite(M4_DIR, 1);
  276.     }
  277.     else
  278.     {
  279.           Serial.println(ERR_CODE);
  280.           Serial.println(spd);
  281.           Serial.println(dir);
  282.           analogWrite(M1_PWM, 0);
  283.           analogWrite(M2_PWM, 0);
  284.           analogWrite(M3_PWM, 0);
  285.           analogWrite(M4_PWM, 0);
  286.     }
  287. }
  288.  
  289. /*
  290. Halt function to stop the rover.
  291. */
  292. void halt()
  293. {
  294.     Serial.println("halt ack");
  295.     analogWrite(M1_PWM, 0);
  296.     analogWrite(M2_PWM, 0);
  297.     analogWrite(M3_PWM, 0);
  298.     analogWrite(M4_PWM, 0);
  299. }
  300.  
  301. /*
  302. Uses the ultrasonic sensor to compute the distance
  303. to the nearest object to the rover.
  304. */
  305. void ping()
  306. {
  307.     Serial.println("ping ack");
  308.     digitalWrite(SONAR_TRIG, LOW); //drive trigger low to settle the pin
  309.     delayMicroseconds(2); //wait for it to settle.
  310.     digitalWrite(SONAR_TRIG, HIGH); //start a pulse
  311.     delayMicroseconds(5); //wait
  312.     digitalWrite(SONAR_TRIG, LOW); //end pulse.
  313.    
  314.     long duration;
  315.     float cm;
  316.    
  317.     duration = pulseIn(SONAR_ECHO, HIGH); //listen for echo and record time in microseconds
  318.     cm = duration/29.0/2.0; //convert time to distance in centimeters.
  319.    
  320.     Serial.println(cm); //send the distance.
  321.    
  322. }
  323.  
  324. /*
  325. Functionally the same as drive, but motors turn in a
  326. different configuration to allow turning.
  327. rate = turn rate (speed) between 0 and 255
  328. dir = direction of rotation r = right, l = left
  329. */
  330. void turn(int rate, char dir)
  331. {
  332.     Serial.println("turn ack");
  333.     if(dir == 'r')
  334.     {
  335.           analogWrite(M1_PWM, rate);
  336.           digitalWrite(M1_DIR, 1);
  337.           analogWrite(M2_PWM, rate);
  338.           digitalWrite(M2_DIR, 0);
  339.           analogWrite(M3_PWM, rate);
  340.           digitalWrite(M3_DIR, 0);
  341.           analogWrite(M4_PWM, rate);
  342.           digitalWrite(M4_DIR, 1);
  343.     }
  344.     else if(dir == 'l')
  345.     {
  346.           analogWrite(M1_PWM, rate);
  347.           digitalWrite(M1_DIR, 0);
  348.           analogWrite(M2_PWM, rate);
  349.           digitalWrite(M2_DIR, 1);
  350.           analogWrite(M3_PWM, rate);
  351.           digitalWrite(M3_DIR, 1);
  352.           analogWrite(M4_PWM, rate);
  353.           digitalWrite(M4_DIR, 0);
  354.     }
  355.     else
  356.     {
  357.           Serial.println(ERR_CODE);
  358.           Serial.println(rate);
  359.           Serial.println(dir);
  360.           analogWrite(M1_PWM, 0);
  361.           analogWrite(M2_PWM, 0);
  362.           analogWrite(M3_PWM, 0);l
  363.           analogWrite(M4_PWM, 0);
  364.     }
  365. }
  366.  
  367. double dist()
  368. {
  369.     digitalWrite(SONAR_TRIG, LOW); //drive trigger low to settle the pin
  370.     delayMicroseconds(2); //wait for it to settle.
  371.     digitalWrite(SONAR_TRIG, HIGH); //start a pulse
  372.     delayMicroseconds(5); //wait
  373.     digitalWrite(SONAR_TRIG, LOW); //end pulse.
  374.    
  375.     long duration;
  376.     float cm;
  377.    
  378.     duration = pulseIn(SONAR_ECHO, HIGH); //listen for echo and record time in microseconds
  379.     cm = duration/29.0/2.0; //convert time to distance in centimeters.
  380.    
  381.     return cm;
  382. }
  383.  
  384. void ecount1()
  385. {
  386.         old1 = new1;
  387.         new1 = digitalRead(ENCODER_1_A)*2 + digitalRead(ENCODER_1_B);
  388.         count1 += QEM[old1*4 + new1];
  389. }
  390.  
  391. void ecount2()
  392. {
  393.         old2 = new2;
  394.         new2 = digitalRead(ENCODER_2_A)*2 + digitalRead(ENCODER_2_B);
  395.         count2 += QEM[old2*4 + new2];
  396. }
  397.  
  398. void ecount3()
  399. {
  400.         old3 = new3;
  401.         new3 = digitalRead(ENCODER_3_A)*2 + digitalRead(ENCODER_3_B);
  402.         count3 += QEM[old3*4 + new3];
  403. }
  404.  
  405. void ecount4()
  406. {
  407.         old4 = new4;
  408.         new4 = digitalRead(ENCODER_4_A)*2 + digitalRead(ENCODER_4_B);
  409.         count4 += QEM[old4*4 + new4];
  410. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement