Advertisement
Guest User

Code for StackOverFlow

a guest
Aug 24th, 2012
222
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.12 KB | None | 0 0
  1. /* S107 3-channel with checksum helicopter control code
  2.  * Copyright (C) 2012, Andrew Barry, Dan Barry
  3.  *
  4.  * Uses an Arduino to control a S107 helicopter
  5.  *
  6.  *
  7.  * Instructions:
  8.  *  Connect an IR LED array to pin 8 (using a FET to amplify the signal)
  9.  *  and use the serial monitor to send commands to the system
  10.  *
  11.  */
  12.  
  13.  
  14.  
  15. #define LED 8
  16.  
  17. #define STATUS 13
  18.  
  19. //#define TAKEOFF_THROTTLE 240
  20. //#define HOLDING_THROTTLE 130
  21.  
  22. byte yawCmd, pitchCmd, throttleCmd, trimCmd;
  23.  
  24. // Set this value for the default channel
  25. // A = 0
  26. // B = 1
  27. // C = 2
  28. byte channel = 0;
  29.  
  30.  
  31. /*
  32.  * Setup function that initializes the serial port and
  33.  * sets some default values for the control variables.
  34.  * Also sets up the pins we'll be using.
  35.  */
  36. void setup()
  37. {
  38.  Serial.begin(9600);
  39.  pinMode(STATUS,OUTPUT);
  40.  digitalWrite(STATUS,LOW);
  41.  
  42.  pinMode(LED,OUTPUT);
  43.  digitalWrite(LED,LOW);
  44.  
  45.  yawCmd = 8;
  46.  pitchCmd = 8;
  47.  trimCmd = 0;
  48.  throttleCmd = 0;
  49.  
  50.  Serial.println("throttle = 0, standing by for commands.");
  51. }
  52.  
  53.  
  54. /*
  55.  * Function that does the actual work of converting commands into
  56.  * IR LED pulses and changes the pins in the appropriate manner.
  57.  */
  58. byte sendPacket(byte yaw, byte pitch, byte throttle, byte trim)
  59. {
  60.  
  61.  
  62.  int packetData[100];
  63.  int pulseNum;
  64.  
  65.  
  66.  digitalWrite(STATUS,HIGH);
  67.  
  68.  
  69.  float channelDelayValue = 136500;
  70.  
  71.  // channel A B or C
  72.  // A is 10 with 136500us packet delay
  73.  // B is 01 with 105200us packet delay
  74.  // C is 11 with 168700us packet delay
  75.  if (channel == 0)
  76.  {
  77.    packetData[0] = 1;
  78.    packetData[1] = 0;
  79.    channelDelayValue = 136500;
  80.  
  81.  } else if (channel == 1)
  82.  {
  83.    packetData[0] = 0;
  84.    packetData[1] = 1;
  85.    channelDelayValue = 105200;
  86.  
  87.  } else {
  88.    packetData[0] = 1;
  89.    packetData[1] = 1;
  90.    channelDelayValue = 168700;
  91.  
  92.  }
  93.  packetData[2] = 0;
  94.  packetData[3] = 0;
  95.  
  96.  // pitch
  97.  
  98.  packetData[7] = (pitch & 0b1000) >> 3; // direction bit
  99.  
  100.  if (pitch < 8)
  101.  {
  102.    pitch = 8 - pitch;
  103.  }
  104.  packetData[6] = (pitch & 0b0100) >> 2; // others are speed bits, note that they are reversed
  105.  packetData[5] = (pitch & 0b0010) >> 1;
  106.  packetData[4] = (pitch & 0b0001);
  107.  
  108.  // throttle
  109.  // bits are reversed in the throttle command
  110.  packetData[15] =  (throttle & 0b10000000) >> 7;
  111.  packetData[14] =  (throttle & 0b01000000) >> 6;
  112.  packetData[13] = (throttle & 0b00100000) >> 5;
  113.  packetData[12] = (throttle & 0b00010000) >> 4;
  114.  
  115.  packetData[11] = (throttle & 0b00001000) >> 3;
  116.  packetData[10] = (throttle & 0b00000100) >> 2;
  117.  packetData[9] = (throttle & 0b00000010) >> 1;
  118.  packetData[8] = (throttle & 0b00000001);
  119.  
  120.  // yaw
  121.  packetData[19] = (yaw & 0b1000) >> 3; // direction bit
  122.  if (yaw < 8)
  123.  {
  124.    yaw = 8 - yaw;
  125.  }
  126.  packetData[18] = (yaw & 0b0100) >> 2;
  127.  packetData[17] = (yaw & 0b0010) >> 1;
  128.  packetData[16] = (yaw & 0b0001);
  129.  
  130.  // these 4 bits are the checksum, so make sure they
  131.  // are 0s so they don't change the XOR later on
  132.  packetData[20] = 0;
  133.  packetData[21] = 0;
  134.  packetData[22] = 0;
  135.  packetData[23] = 0;
  136.  
  137.  // yaw trim / yaw adjust (the little dial on the controller)
  138.  // 6 bits
  139.  packetData[24] = 0;
  140.  packetData[25] = 0;
  141.  packetData[26] = 0;
  142.  packetData[27] = 0;
  143.  
  144.  packetData[28] = 0;
  145.  packetData[29] = 0;
  146.  
  147.  // these bits are never sent but we do the checksum
  148.  // computation in 4-bit chunks, with the trailing two
  149.  // bits set to zero, so we set them to zero here to make
  150.  // the checksum a bit easier to compute
  151.  packetData[30] = 0;
  152.  packetData[31] = 0;
  153.  
  154.  int i;
  155.  
  156.  int checksum[10];
  157.  checksum[0] = 0;
  158.  checksum[1] = 0;
  159.  checksum[2] = 0;
  160.  checksum[3] = 0;
  161.  
  162.  // compute checksum -- bitwise XOR of 4-bit chuncks
  163.  // with two zeros padding the *end* of the last two bits
  164.  for (i=0; i<32; i+=4)
  165.  {
  166.    // XOR
  167.    checksum[0] = packetData[i + 0] ^ checksum[0]; // the "^" operator is bitwise XOR (exclusive OR)
  168.    checksum[1] = packetData[i + 1] ^ checksum[1];
  169.    checksum[2] = packetData[i + 2] ^ checksum[2];
  170.    checksum[3] = packetData[i + 3] ^ checksum[3];
  171.  }
  172.  
  173.  // now set bits 21-24 (array values 20-23) to the checksum
  174.  packetData[20] = checksum[0];
  175.  packetData[21] = checksum[1];
  176.  packetData[22] = checksum[2];
  177.  packetData[23] = checksum[3];
  178.  
  179.  /*
  180.   * Uncomment for realtime display of packet data
  181.   */
  182.   /*
  183.  for (i=0; i<30; i++)
  184.  {
  185.    Serial.print(packetData[i]);
  186.    if ((i+1)%4 == 0)
  187.    {
  188.      Serial.print(" ");
  189.    }
  190.  }
  191.  Serial.println(" ");
  192.  */
  193.  
  194.  // Send the packet by flashing the LEDs.  Also remember how long the packet takes to send
  195.  // so we can properly compute how long to wait before sending the next packet.
  196.  int bitsum = 0;
  197.  
  198.  for (i=0; i<30; i++)
  199.  {
  200.    // a "0" bit is 16 pulses and a "1" bit is 32 pulses
  201.    if (packetData[i] == 1)
  202.    {
  203.      bitsum ++;
  204.      pulseNum = 32;
  205.    } else {
  206.      pulseNum = 16;
  207.    }
  208.  
  209.    // flash pulseNum times
  210.    // a "0" bit is 16 pulses and a "1" bit is 32 pulses
  211.    while(pulseNum--)
  212.    {
  213.      digitalWrite(LED,LOW);
  214.      delayMicroseconds(9);
  215.      digitalWrite(LED,HIGH);
  216.      delayMicroseconds(8);
  217.    }
  218.    
  219.    // there is a 300 microsecond delay between pulses of the LED
  220.    delayMicroseconds(300);
  221.  }
  222.  
  223.  // channel A B or C
  224.  // A is 10 with 136500us packet delay
  225.  // B is 01 with 105200us packet delay
  226.  // C is 11 with 168700us packet delay
  227.  //
  228.  // that is the delay between sending 30 bit packets
  229.  // note that this does not change if our packets are longer
  230.  // or shorter, so we must take that into account
  231.  
  232.  return((channelDelayValue - bitsum * 272)/1000); // in ms.
  233.  
  234. }
  235.  
  236.  
  237. void HoldCommand(int yawIn, int pitchIn, int throttleIn, int delayTime)
  238. {
  239.   Serial.print("Holding: Yaw:");
  240.   Serial.print(yawIn);
  241.   Serial.print(" Pitch: ");
  242.   Serial.print(pitchIn);
  243.   Serial.print(" Throttle: ");
  244.   Serial.print(throttleIn);
  245.   Serial.print(" for ");
  246.   Serial.print(delayTime);
  247.   Serial.println("ms");
  248.  
  249.   int i;
  250.   int delayConst = 50;
  251.  
  252.  
  253.   int delayAmount = delayTime/delayConst;
  254.   int packetDelay;
  255.  
  256.   while (delayTime > 0)
  257.   {
  258.     if (Serial.available() == true)
  259.     {
  260.       Serial.println("HOLD ABORTED");
  261.       break;
  262.     }
  263.  
  264.  
  265.     packetDelay = sendPacket(yawIn, pitchIn, throttleIn, trimCmd);
  266.     delayTime = delayTime - packetDelay;
  267.  
  268.     delay(packetDelay);
  269.  
  270.     delay(delayAmount);
  271.     delayTime = delayTime - delayAmount;
  272.   }
  273.   Serial.println("Done holding.");
  274. }
  275.  
  276. void Land()
  277. {
  278.  static int i;
  279.  Serial.println("Landing");
  280.  for(i=throttleCmd;i>0;i--){
  281.    HoldCommand(8,8,throttleCmd,50);
  282.  }  
  283.  throttleCmd = 0;
  284. }
  285.  
  286.  
  287.  
  288.  
  289. /*
  290.  * Function that manages recieving data from the serial port.
  291.  * Mostly changes the global variables that are passed to the
  292.  * control functions.
  293.  */
  294. void serialEvent()
  295. {
  296.  char cmd = Serial.read();
  297.  Serial.println();
  298.  Serial.print("command received is ");
  299.  Serial.println(cmd);
  300.  
  301.  switch (cmd)
  302.  {
  303.    // Take off with 't'
  304.    case 't':
  305.      Serial.println("Taking Off");
  306.  
  307.      // Yaw: 1-15
  308.      //    8 = no turn
  309.      //    1 = max right turn
  310.      //    15 = max left turn
  311.      //
  312.      // Pitch: 1-15
  313.      //    8 = no pitch
  314.      //    15 = max forward
  315.      //    1 = max backwards
  316.      //
  317.      // Throttle: 0-255
  318.      //    0 = off
  319.      //    ~130 = steady flight
  320.      //    ~240 = fast climb
  321.      
  322.      // First, go up with lots of throttle for 650ms
  323.      // yaw: 8 --> no yaw
  324.      // pitch: 8 --> no pitch
  325.      // throttle: 240 --> fast climb
  326.      // delay: 650ms --> enough time to climb, not too long so won't hit ceiling
  327.      
  328.      // HoldCommand: a function that sends the same data for a given amount of time
  329.      // HoldCommand(yaw, pitch, throttle, time-to-hold-in-ms);
  330.      HoldCommand(8, 8, 240, 650);
  331.      
  332.      
  333.      // set the *global* throttle to steady flight throttle
  334.      throttleCmd = 130;
  335.      break;
  336.  
  337.    // land with 'x' or 'q'
  338.    case 'x':
  339.    case 'q':
  340.      Land();
  341.      break;
  342.  
  343.    // throttle commands
  344.    case '0':
  345.    case '1':
  346.    case '2':
  347.    case '3':
  348.    case '4':
  349.    case '5':
  350.    case '6':
  351.    case '7':
  352.    case '8':
  353.    case '9':
  354.      throttleCmd = atoi(&cmd) * 25;  //single character, so we can go from 0 to 255 by inputting 0 to 9 in the serial monitor
  355.      break;
  356.  
  357.    // turn left
  358.    case 'a':
  359.      if (yawCmd < 15)
  360.      {
  361.        yawCmd ++;
  362.      }
  363.      Serial.print("Yaw is ");
  364.      Serial.println(yawCmd);
  365.      break;
  366.  
  367.    // turn right
  368.    case 'd':
  369.      if (yawCmd > 1)
  370.      {
  371.        yawCmd --;
  372.      }
  373.      Serial.print("Yaw is ");
  374.      Serial.println(yawCmd);
  375.      break;
  376.  
  377.    // move forwards
  378.    case 'w':
  379.      if (pitchCmd < 15){
  380.        pitchCmd ++;  // moves forward
  381.      }
  382.      Serial.print("Pitch is ");
  383.      Serial.println(pitchCmd);
  384.      break;
  385.  
  386.    // move backwards
  387.    case 's':
  388.      if (pitchCmd > 1)
  389.      {
  390.        pitchCmd --;  // moves backward
  391.      }
  392.      Serial.print("Pitch is ");
  393.      Serial.println(pitchCmd);
  394.      break;
  395.  
  396.    // increase throttle
  397.    case 'u':
  398.      if (throttleCmd < 255 - 6)
  399.      {
  400.        throttleCmd += 6;
  401.      }
  402.      Serial.print("Throttle is ");
  403.      Serial.println(throttleCmd);
  404.      break;
  405.    
  406.    // decrease throttle
  407.    case 'j':
  408.      if (throttleCmd > 6)
  409.      {
  410.        throttleCmd -= 6;
  411.      }
  412.      Serial.print("Trottle is ");
  413.      Serial.println(throttleCmd);
  414.      break;
  415.  
  416.    // change channel
  417.    case 'c':
  418.      Serial.println("Changing channel");
  419.      if (channel >= 2)
  420.      {
  421.        channel = 0;
  422.      } else
  423.      {
  424.        channel ++;
  425.      }
  426.      Serial.print("Channel is: ");
  427.      Serial.println(channel);
  428.      break;
  429.  
  430.    // reset yaw and pitch
  431.    case 'r':
  432.      Serial.println("resetting yaw and pitch");
  433.      yawCmd = 8;
  434.      pitchCmd = 8;
  435.      break;
  436.  
  437.  
  438.    default:
  439.      Serial.println("Unknown command");
  440.  }
  441.  Serial.print("Throttle is at ");
  442.  Serial.println(throttleCmd);
  443. }
  444.  
  445. /*
  446.  * Loops continuously sending and delaying for the transmission
  447.  */
  448. void loop()
  449.  
  450. {
  451.    // Note that serialEvent() gets called on each path of the loop
  452.    // and runs if there is data at the serial port
  453.  
  454.    // we call delay here on the return value of sendPacket because that will
  455.    // cause us to put the right amount of time between packets.  The delay is
  456.    // not constant, but is instead based on how long the packet was
  457.    // that we sent
  458.    delay(sendPacket(yawCmd, pitchCmd, throttleCmd, trimCmd));
  459. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement