Advertisement
Guest User

Untitled

a guest
Mar 30th, 2015
217
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.72 KB | None | 0 0
  1. #define EXTEND_PIN 5
  2. #define RETRACT_PIN 3
  3. #define SENSOR_PIN A1
  4.  
  5. // Position of the piston
  6. int Position = 0;
  7. int prev_position = 0;
  8. int tolerance = 1 << 4; // Position tolerance of 1/64 total (theoretical) travel.
  9. int projected = 0;
  10.  
  11. // Filtering variables
  12. int raw_position = 0;
  13.  
  14. // input variables
  15. int input = 0;
  16. int target = 0;
  17.  
  18. // Valve state variables
  19. #define CLOSED 0
  20. #define EXTENDING 1
  21. #define RETRACTING 2
  22. int valve_state = CLOSED;
  23. //int new_state = CLOSED;
  24. //unsigned long valve_last_changed = millis();
  25. //#define VALVE_ACTIVATION 12
  26.  
  27. // Toggle whether or not to limit further changes in movement
  28. bool freeze = true;
  29.  
  30. const int tick = 8;
  31.  
  32. // Timing variables
  33. unsigned long dong;
  34. unsigned long now;
  35. unsigned long last_tick;
  36. unsigned long time_delta;
  37.  
  38. // Psuedo-velocity value; assumes constant-enough loop time
  39. int raw_velocity = 0;
  40. int velocity = 0;
  41. #define V_MULTIPLIER 10
  42. // 'Velocity' threshold to consider stopped.
  43. // TODO: Measure/santiy-check; possibly update dynamically.
  44. int v_min = 40;
  45.  
  46.  
  47. void setup() {
  48.  
  49.   pinMode(EXTEND_PIN,OUTPUT);
  50.   pinMode(RETRACT_PIN,OUTPUT);
  51.   pinMode(SENSOR_PIN,INPUT);
  52.  
  53.   Serial.begin(115200);
  54.   // Set target so piston doesn't suddenly move upon startup
  55.   target = analogRead(SENSOR_PIN);
  56.   // Initialize microsmoothing filter
  57.   //*input_history = target;
  58.   Position = target;
  59.   // Set initial timestamp
  60.   dong = millis();
  61.   last_tick = dong;
  62.  
  63. }
  64.  
  65.  
  66. void loop() {
  67.  
  68.   //delay(1); // Make sure there's enough delay in the loop to actualy get meaningful velocity
  69.   // Read input & 'unfreeze' if input is available.
  70.   // TODO: Replace 'if' block with function leveraging Firmata protocol
  71.   if (Serial.available() > 0) {
  72. //    input = Serial.read();
  73. //    target = 4 * input;
  74.   input = Serial.read() - '0';
  75.   target = 100 * input;
  76.     Serial.print("Position: ");
  77.     Serial.println(Position);
  78.     Serial.print("Target: ");
  79.     Serial.println(target);
  80.     // Unfreeze to allow motion. Only time freeze is ever set to false.
  81.     freeze = false;
  82.   }
  83.  
  84.   now = millis();
  85.  
  86.   time_delta = now - dong;
  87.   if (time_delta == 0) { // Probably unnecessary, but divide by zero can make chips explode.
  88.     return;
  89.   }
  90.   // Read position
  91.   raw_position = analogRead(SENSOR_PIN);
  92.   ema_filter(raw_position, &Position);
  93.  
  94.   // Calculate velocity
  95.   raw_velocity = ((V_MULTIPLIER * Position) - (V_MULTIPLIER * prev_position)) / (int)time_delta;  // Division is painfully slow
  96.   ema_filter(raw_velocity, &velocity);
  97.   Serial.print(raw_position); Serial.print(" ");
  98.   Serial.print(Position); Serial.print(" ");
  99.   Serial.print(time_delta); Serial.print(" ");
  100.   Serial.print(raw_velocity); Serial.print(" ");
  101.   Serial.println(velocity);
  102.  
  103.   // Update old state
  104.   prev_position = Position;
  105.   dong = now;
  106.  
  107.   // If it hasn't been a tick, restart loop. Otherwise update solenoid control
  108.   if ((now - last_tick) < tick) {
  109.     return;
  110.   }
  111.   // Update tick timestamp
  112.   last_tick = now;
  113.  
  114.   //===============================================================//
  115.   //======================== Control logic ========================//
  116.   //===============================================================//
  117.  
  118.   // projected position = position + velocity * tick_length
  119.   projected = Position + (velocity / V_MULTIPLIER * tick);
  120.   //Serial.println(velocity);
  121.  
  122.   if (velocity > v_min) { // physically extending
  123.     if (projected > target + tolerance) {  // Going too fast
  124.       Serial.println("State 1");
  125.       switch (valve_state) {
  126.         case CLOSED:
  127.           if (freeze) {
  128.             // No change
  129.             break;
  130.           }
  131.           set_valve(RETRACTING);
  132.           break;
  133.         case EXTENDING:
  134.           //freeze = true;
  135.           set_valve(RETRACTING);
  136.           break;
  137.         case RETRACTING:
  138.           if (freeze) {
  139.             set_valve(CLOSED);
  140.           } // else: No change
  141.           break;
  142.       }
  143.     // velocity > v_min
  144.     } else if (projected < target - tolerance) { // Keep going
  145.       Serial.println("State 2");
  146.       switch (valve_state) {
  147.         case CLOSED: // Identical to RETRACTING below
  148.           if (freeze) {
  149.             // No change
  150.             break;
  151.           } else {
  152.             set_valve(EXTENDING);
  153.           }
  154.           break;
  155.         case EXTENDING:
  156.           // No change
  157.           break;
  158.         case RETRACTING:
  159.           if (freeze) {
  160.             set_valve(CLOSED);
  161.           } else {
  162.             set_valve(EXTENDING);
  163.           }
  164.           break;
  165.       }
  166.     } else { // velocity > 0, projected ~= target
  167.      Serial.println("State 3");
  168.       switch (valve_state) {
  169.         case CLOSED:
  170.          // freeze = true;
  171.           // Valve is already closed
  172.           break;
  173.         case EXTENDING:
  174.           // freeze is unchanged
  175.           set_valve(CLOSED);
  176.           break;
  177.         case RETRACTING:
  178.           freeze = true;
  179.           Serial.print("Frozen ");
  180.           set_valve(CLOSED);
  181.           break;
  182.       }
  183.     }
  184.   } else if (velocity < -v_min) {  // physically retracting
  185.     if (projected > target + tolerance) {  // Keep going
  186.       Serial.println("State 4");
  187.       switch (valve_state) {
  188.         case CLOSED:
  189.           if (freeze) {
  190.             // No change
  191.             break;
  192.           } else {
  193.             set_valve(RETRACTING);
  194.           }
  195.           break;
  196.         case EXTENDING:
  197.           if (freeze) {
  198.             set_valve(CLOSED);
  199.           } else {
  200.             set_valve(RETRACTING);
  201.           }
  202.           break;
  203.         case RETRACTING:
  204.           // No change
  205.           break;
  206.       }
  207.     // velocity < -v_min, retracting
  208.     } else if (projected < target - tolerance) {  // Going too fast
  209.       Serial.println("State 5");
  210.       switch (valve_state) {
  211.         case CLOSED:
  212.           if (freeze) {
  213.             // No change
  214.             break;
  215.           } // else: Deliberately fall through
  216.         case RETRACTING:
  217.           //freeze = true;
  218.           set_valve(EXTENDING);
  219.           break;
  220.         case EXTENDING:
  221.           if (freeze) {
  222.             set_valve(CLOSED);
  223.           } // else: No change
  224.           break;
  225.       }
  226.     } else { // velocity < 0, projected ~= target
  227.       Serial.println("State 6");
  228.       switch (valve_state) {
  229.         case CLOSED:
  230.           //freeze = true;
  231.           // Valve already closed
  232.           break;
  233.         case EXTENDING:
  234.           freeze = true;
  235.           Serial.print("Frozen ");
  236.           set_valve(CLOSED);
  237.           break;
  238.         case RETRACTING:
  239.           // freeze is unchanged
  240.           set_valve(CLOSED);
  241.           break;
  242.       }
  243.     }
  244.   } else { // Velocity ~= 0
  245.     //Serial.println("~0 velocity");
  246.     if (freeze) {
  247.       //Serial.println("7");
  248.       set_valve(CLOSED);
  249.     } else { // freeze == false
  250.       if (Position > target + tolerance) {
  251.         //Serial.println("8");
  252.         set_valve(RETRACTING);
  253.       } else if (Position < target - tolerance) {
  254.         //Serial.println("9");
  255.         set_valve(EXTENDING);
  256.       } else { // Position ~= target, velocity ~= 0  ==> no movement
  257.        Serial.print("Frozen ");
  258.        Serial.println(Position);
  259.         freeze = true;
  260.         set_valve(CLOSED);
  261.       }
  262.     }
  263.   }
  264.  
  265.   //===============================================================//
  266.   //====================== End control logic ======================//
  267.   //===============================================================//
  268. }
  269.  
  270. /*
  271.       switch (valve_state) {
  272.         case CLOSED:
  273.          
  274.           break;
  275.         case EXTENDING:
  276.          
  277.           break;
  278.         case RETRACTING:
  279.          
  280.           break;
  281.       }
  282. */
  283.  
  284.  
  285. void set_valve(int new_state) {
  286.   //Serial.println(new_state);
  287.  
  288.   if (valve_state == new_state) {
  289.     return;
  290.   }
  291. //  if ((millis() - valve_last_changed) < VALVE_ACTIVATION) {
  292. //    return -1;
  293. //  }
  294.   switch (new_state) {
  295.     case CLOSED:
  296.       Serial.println("CLOSED");
  297.       digitalWrite(RETRACT_PIN, LOW);
  298.       digitalWrite(EXTEND_PIN, LOW);
  299.       break;
  300.     case EXTENDING:
  301.       Serial.println("EXTENDING");
  302.       digitalWrite(RETRACT_PIN, LOW);
  303.       digitalWrite(EXTEND_PIN, HIGH);
  304.       break;
  305.     case RETRACTING:
  306.       Serial.println("RETRACTING");
  307.       digitalWrite(EXTEND_PIN, LOW);
  308.       digitalWrite(RETRACT_PIN, HIGH);
  309.       break;
  310.   }
  311.   valve_state = new_state;
  312. //  valve_last_changed = millis();
  313. //  return 1;
  314. }
  315.  
  316. // Uses an alpha of 1/8 to enable bit-shifting.
  317. void ema_filter(int input_value, int *average) {
  318.    *average = ( 2 * input_value + 18 * (*average) ) / 20;
  319. //  *average = ((input_value << 2) + // input * 4
  320. //              (*average << 5) - (*average << 2) + // average * (32 - 4)
  321. //              16 // Add 2^4 to cause bitshift below to round instead of truncate
  322. //             ) >> 5; // divide by 32
  323. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement