Advertisement
Guest User

Untitled

a guest
Dec 4th, 2014
308
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.90 KB | None | 0 0
  1. #include <SPI.h>
  2. #include <nRF24L01.h>
  3. #include <RF24.h>
  4.  
  5. /* Pin definitions */
  6. #define JOYSTICK_1_X_PIN A3
  7. #define JOYSTICK_1_Y_PIN A2
  8. #define JOYSTICK_1_BUTTON_PIN 5
  9.  
  10. #define JOYSTICK_2_X_PIN A1
  11. #define JOYSTICK_2_Y_PIN A0
  12. #define JOYSTICK_2_BUTTON_PIN 6
  13.  
  14. #define JOYSTICK_THRESHOLD 50
  15.  
  16. #define MODE_TOGGLE_BUTTON_PIN 7
  17. #define CALIBRATE_BUTTON_PIN A5
  18.  
  19. #define BLUE_LED_PIN 3
  20. #define RED_LED_PIN 4
  21. #define GREEN_LED_PIN A4
  22.  
  23. #define RADIO_CE_PIN 9
  24. #define RADIO_CSN_PIN 10
  25.  
  26. /* Timeout between each calibration constant */
  27. #define CALIBRATION_TIME 1000
  28.  
  29. /* How long to hold the "Mode" button down for automatic mode to be engaged */
  30. #define ENGAGE_AUTO_MODE_DOWN_TIME 1000
  31.  
  32. /* Enums used for better readability of values / array indexes */
  33. enum Side {
  34.     LOWER,
  35.     MIDDLE,
  36.     UPPER
  37. };
  38. enum Mode {
  39.     WATERMODE,
  40.     FIREMODE,
  41.     AUTOMODE
  42. };
  43. enum OnOff {
  44.     OFF,
  45.     ON
  46. };
  47.  
  48. /*
  49.     Class to handle the joysticks. If they were perfectly calibrated from the start, these would not have
  50.     been neccesearly. However seeing how much trouble we had with our readings, and how the
  51.     lower/middle/upper value seemed to differ, this was needed.
  52. */
  53. class Joystick {
  54.     private:
  55.         int pin, threshold, lowerOut, upperOut, middleOut;
  56.         int bounds[3]; //lower, middle and upper value
  57.     public:
  58.         Joystick(int p, int t) {
  59.             pin = p;
  60.             threshold = t;
  61.  
  62.             bounds[0] = 512;
  63.             bounds[1] = 0;
  64.             bounds[2] = 1023; //boundaries in ideal conditions (before calibration)
  65.             lowerOut = 0; //standard out values, in this case 0, 511, 1023. No negative values due to bitshift
  66.             upperOut = 1023;
  67.             middleOut = (upperOut + lowerOut) / 2;
  68.  
  69.             pinMode(pin, INPUT);
  70.         }
  71.         int get() {
  72.             int value = analogRead(pin); //value from the joystick
  73.             int valueWithOffset = value - bounds[0]; //value "middle" as zero point
  74.             if(abs(valueWithOffset) < threshold) return middleOut; //if the value is within the threshold (zero area)
  75.             /* mapping functions to make sure each 'side' has 512 values regardless of the actual case */
  76.             if(valueWithOffset < 0) value = map(value, bounds[1], bounds[0], lowerOut, middleOut);
  77.             else if(valueWithOffset > 0) value = map(value, bounds[0], bounds[2], middleOut, upperOut);
  78.             else value = middleOut;
  79.  
  80.             /* constrain the value within the bounds */
  81.             return constrain(value, lowerOut, upperOut);
  82.         }
  83.         void calibrate(int s) {
  84.             /* calibrate a given side (LOWER, MIDDLE, UPPER). Setting the bounds. */
  85.             bounds[s] = analogRead(pin);
  86.         }
  87. };
  88.  
  89. /*
  90.     Toggle class to handle a standard toggle. can toggle between the numbers of states set
  91.     and be set to a state of choosing
  92. */
  93.  
  94. class Toggle {
  95.     protected:
  96.         byte state; //current state
  97.         byte numStates; //number of states available
  98.         bool togglable; //if the instance can be toggled
  99.     public:
  100.         Toggle(byte s) {
  101.             numStates = s;
  102.             state = 0;
  103.             togglable = 1;
  104.         }
  105.         /* method to set the state. virutal so that child classes can overwrite  */
  106.         virtual void setState(byte s) {
  107.             state = s;
  108.         }
  109.         void toggle() {
  110.             if(!togglable) return; //toggle only if its allowed
  111.             state++; //inclease state
  112.             state = state % numStates; //if state surpasses the alloved number of states, start over
  113.             togglable = 0; //do not allow to toggle again before 'reset' is called
  114.         }
  115.         void reset() {
  116.             togglable = 1; //allow toggle
  117.         }
  118.         byte getState() {
  119.             return state; //get current state
  120.         }
  121. };
  122.  
  123. /*
  124.     LedToggle extends Toggle to add a led feature. Each state has a led on a given pin number and this led
  125.     is set to high when that state is active
  126. */
  127. class LedToggle : public Toggle {
  128.     private:
  129.         //static array for simplicity. maximum of ten leds available
  130.         int leds[10];
  131.     public:
  132.         LedToggle(byte pins[], byte states) : Toggle(states) {
  133.             //set correct pinMode to each led
  134.             for(int i = 0; i < states; i++) {
  135.                 leds[i] = pins[i];
  136.                 pinMode(leds[i], OUTPUT);
  137.             }
  138.         }
  139.         /*  
  140.             overwrite parentclass setState. this does the same, but also changes sets the led of the
  141.             current state to high and the others to low
  142.         */
  143.         virtual void setState(byte s) {
  144.             state = s;
  145.             for(int i = 0; i < numStates; i++) {
  146.                 if(s == i) digitalWrite(leds[i], 1);
  147.                 else digitalWrite(leds[i], 0);
  148.             }
  149.         }
  150. };
  151.  
  152. /* Function to encode an array to a 64 bit bitsequence */
  153. uint64_t intarrToUint64(int data[], int keep[], int dataSize) {
  154.     uint64_t compression = 0; //initialize variable
  155.     for(int i = 0; i < dataSize; i++) {
  156.         /*
  157.             For each loop left shift the variable by x bits assigned in 'keep'. Then read in and
  158.             store the data in that area of the variable.
  159.         */
  160.         compression = (compression << keep[i]) | data[i];
  161.     }
  162.     return compression;
  163. }
  164. /* Function to encode a 64 bit variable into a byte array */
  165. void uint64ToByteArr(uint64_t data, byte arr[], int byteSize) {
  166.     //loop over the number of bytes wanted
  167.     for(int i = 0; i < byteSize; i++) {
  168.         arr[byteSize - i - 1] = data & 0xFF; //read in the least significant byte
  169.         data >>= 8; //right shift the data with a byte
  170.     }
  171. }
  172.  
  173. const uint64_t pipe = 0xF0F0F0F0AALL; //radio pipe for communication
  174.  
  175. RF24 radio(RADIO_CE_PIN, RADIO_CSN_PIN);
  176.  
  177. /* Initializing the joysticks on their respective pins */
  178. Joystick j1x(JOYSTICK_1_X_PIN, JOYSTICK_THRESHOLD);
  179. Joystick j1y(JOYSTICK_1_Y_PIN, JOYSTICK_THRESHOLD);
  180. Joystick j2x(JOYSTICK_2_X_PIN, JOYSTICK_THRESHOLD);
  181. Joystick j2y(JOYSTICK_2_Y_PIN, JOYSTICK_THRESHOLD);
  182.  
  183. /* Initialize the two toggles, one with leds and 3 states, one with 2 states (on/off) */
  184. LedToggle modeToggle( (byte[]){BLUE_LED_PIN, RED_LED_PIN, GREEN_LED_PIN}, 3);
  185. Toggle guideFlameToggle(2);
  186.  
  187. int data[8]; //temporary array of integers as theyre read in
  188. int bitsToKeep[] = {10, 10, 1, 10, 10, 1, 2, 1}; //how many bits of each int needed
  189. long timeDown; //how long a button is pressed down
  190.  
  191. void setup() {
  192.     /* Initializing variable */
  193.     Serial.begin(9600);
  194.     radio.begin();
  195.     radio.setPayloadSize(6);
  196.     radio.openWritingPipe(pipe);
  197.  
  198.     /* Setting startup modes */
  199.     modeToggle.setState(WATERMODE);
  200.     guideFlameToggle.setState(OFF);
  201. }
  202.  
  203. void loop() {
  204.  
  205.     /* Toggle functions to switch between the three modes, and turnining the pilot flame on and off */
  206.  
  207.     //if the mode button is held down
  208.     if(digitalRead(MODE_TOGGLE_BUTTON_PIN)) {
  209.         if(timeDown == 0) timeDown = millis(); //start timer for how long it has been down
  210.         //if the button has been held down for the given ammount of time, engage automatic mode
  211.         else if(millis() - timeDown > ENGAGE_AUTO_MODE_DOWN_TIME) modeToggle.setState(AUTOMODE);
  212.     } else if(timeDown != 0) {
  213.         //if the button was recently released
  214.         if(millis() - timeDown < ENGAGE_AUTO_MODE_DOWN_TIME) { //if automatic mode has not been started
  215.             if(modeToggle.getState() == WATERMODE) modeToggle.setState(FIREMODE); //switch to firemode
  216.             else {
  217.                 //switch to watermode and ensure the pilot flame is turned off
  218.                 guideFlameToggle.setState(0);
  219.                 modeToggle.setState(WATERMODE);
  220.             }
  221.         }
  222.         //reset the timer
  223.         timeDown = 0;
  224.     }
  225.     else modeToggle.reset(); //reset the mode toggle so it may be toggled again
  226.  
  227.     //turn on pilot flame if fire mode is engaged and the joystick is pressed down. reset elsewise
  228.     if(!digitalRead(JOYSTICK_1_BUTTON_PIN) && modeToggle.getState() == FIREMODE) guideFlameToggle.toggle();
  229.     else guideFlameToggle.reset();
  230.  
  231.     //temporary storage for all data to be sent
  232.     data[0] = j1x.get();
  233.     data[1] = j1y.get();
  234.     data[2] = guideFlameToggle.getState();
  235.     data[3] = j2x.get();
  236.     data[4] = j2y.get();
  237.     data[5] = !digitalRead(JOYSTICK_2_BUTTON_PIN);
  238.     data[6] = modeToggle.getState();
  239.     data[7] = 1; //last bit always 1 to ensure no all 0 data packets are sent, as the radio likes to ignore them
  240.  
  241.     //temporary storage in a 64 bit variable
  242.     uint64_t dataToSend = intarrToUint64(data, bitsToKeep, 8);
  243.  
  244.     //encode the 64 bit variable to an array of 6 bytes
  245.     byte arr[6];
  246.     uint64ToByteArr(dataToSend, arr, 6);
  247.  
  248.     /* total compression is now from 32 byte to 6 byte */
  249.  
  250.     radio.write(arr, 6); //write it to the radio pipe
  251.  
  252.  
  253.     // if calibration is wanted
  254.     if(digitalRead(CALIBRATE_BUTTON_PIN)) {
  255.         //save the current mode
  256.         int modeBeforeCalibration = modeToggle.getState();
  257.  
  258.         //delay
  259.         delay(CALIBRATION_TIME);
  260.         /*
  261.             calibrate all sides in first x then y direction. the first calibration (middle) is set to both x and y
  262.         */
  263.         for(int i = 0; i < 3; i++) {
  264.             digitalWrite(BLUE_LED_PIN, 1);
  265.             digitalWrite(GREEN_LED_PIN, 1);
  266.             delay(CALIBRATION_TIME);
  267.             j1x.calibrate(i);
  268.             j2x.calibrate(i);
  269.             if(i == 0) {
  270.                 j1y.calibrate(i);
  271.                 j2y.calibrate(i);
  272.             }
  273.             digitalWrite(BLUE_LED_PIN, 0);
  274.             digitalWrite(GREEN_LED_PIN, 0);
  275.             delay(CALIBRATION_TIME);
  276.         }
  277.         for(int i = 1; i < 3; i++) {
  278.             digitalWrite(BLUE_LED_PIN, 1);
  279.             digitalWrite(GREEN_LED_PIN, 1);
  280.             delay(CALIBRATION_TIME);
  281.             j1y.calibrate(i);
  282.             j2y.calibrate(i);
  283.             digitalWrite(BLUE_LED_PIN, 0);
  284.             digitalWrite(GREEN_LED_PIN, 0);
  285.             if(i != 2) delay(CALIBRATION_TIME);
  286.         }
  287.         // revert to the state before calibration
  288.         modeToggle.setState(modeBeforeCalibration);
  289.     }
  290. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement