// Author : Quentin BENETHUILLERE // Date of creation : 2021/05/12 // Last modification : 2021/05/31 /* * Program function(s): * This program is meant for the daughter board of the puzzle box that I designed for the FabAcademy program 2021. * It handles the following functions : * - Communication with the main board using i2c protocol. Basically it answers requests from the main board in order to know when puzzles 1 and 2 are solved. * - Implements the logics for puzzles 1 and 2. * - Controls a RGB LED based on user inputs related to puzzles 1 and 2. * ------------------------------------------------------ * Puzzle 1 : requests capacitive sensors (made out of copper) to be touched in a specified order to solve it. * -> when touching any sensor the blue LED blinks. * -> when sensors have been touched in the expected order, the green LED turns ON for a calibrated amount of time. * -> when sensors have been touched in an order that is not the expected one, the red LED turns ON for a calibrated amount of time. * -> Note : in this program it is not possible to perform 2 consecutive touches on the same sensor. * -> after a calibrated amount of time without any sensor to be touched, the sequence is reinitialiazed. * -> if several sensors are touched simultaneously, only the first one in the identification order will be considered. * ------------------------------------------------------ * Puzzle 2 : requests user to successively connect a wire from a known GND pin, to different locations following a given sequence. * -> each connection between the GND source and any connector makes the RGB LED blinks blue. * -> when connections have not been established in the expected order, the RBG LED turns red for a calibrated amount of time. * -> when connections have been established in the right order, the RGB LED turns green for a calibrated amount of time. * -> Note : in this program it is not possible to perform 2 consecutive connections on the same connector. * -> after a calibrated amount of time without any new connection established, the sequence is reinitialiazed, and the RGB LED blinks orange. */ //* ----------- //* LIBRAIRIES //* ----------- #include // Library for i2c communication. #include // Library for capacitive sensors. // ------------------------- // DECLARATION OF DEFINES // ------------------------- // Defining colors association for the RGB LED : #define RGB_LED_OFF 0 #define RED 1 #define GREEN 2 #define BLUE 3 #define WHITE 4 //#define COMMON_ANODE // //uncomment this line ONLY if using a Common Anode RGB LED. // ------------------------- // DECLARATION OF VARIABLES // ------------------------- // ------------------------------------------------ // Adjustable variables (program main parameters) // ------------------------------------------------ // Puzzle 1 (capacitive sensors) : const int DETECTION_THRESHOLD = 800; // Threshold above which a touch on a capacitive sensor is considered. Value to be adjusted based on the circuit, and capacitive sensors used. const int CAPACITIVE_MEASUREMENT = 30; // Determines the resolution for the capacitive touch measurement. 30 used in the examples I found. const byte sequence_length_sensors = 7; // Length of the expected sequence of touches to be performed for solving the puzzle. //const byte expected_sequence_sensors[sequence_length_sensors]={5,1,6,2,3,4,7}; // Expected sequence of touches to be performed for solving the puzzle. const byte expected_sequence_sensors[sequence_length_sensors]={1,2,3,4,5,6,7}; // Expected sequence of touches to be performed for solving the puzzle. const byte nb_sensors=7; // Number of capacitive sensors. // Puzzle 2 (world map) : const byte sequence_length_world = 5; // Length of the expected sequence of connections to establish to solve the puzzle. const byte expected_sequence_world[sequence_length_world]={1,2,3,4,5}; // Expected sequence of connections to establish for solving the puzzle. const byte nb_inputs_world=5; // Number of inputs on the world map (basically one per world area). // Global : const long TIMER_REINITIALIZATION = 10000; // Timer after which the sequence is reinitialized if no new connection/new touch is detected. const int TIMER_ERROR = 3000; // Timer for which red LED is turned on following an error. const int TIMER_SUCCESS = 6000; // Timer for which green LED is turned on once puzzle is completed. const int TIMER_BLINK = 600; // Timer for which LED blinks (when reinitialization takes place, or for each touch/connection performed). const byte i2c_daughter_board_address = 9; // i2c address given to the daughter board. // ------------------------------------------------ // PIN connections // ------------------------------------------------ // Digital const byte PIN_region_1 = 20; // PIN related to region 1. const byte PIN_region_2 = 21; // PIN related to region 2. const byte PIN_region_3 = 6; // PIN related to region 3. const byte PIN_region_4 = 7; // PIN related to region 4. const byte PIN_region_5 = 8; // PIN related to region 5. //const byte PIN_region_6 = 14; // PIN related to region 6. const byte PIN_list[nb_inputs_world] = {PIN_region_1, PIN_region_2, PIN_region_3, PIN_region_4, PIN_region_5}; // list of the pins related to regions for code optimization. const byte PIN_sensor_emitter = 15; // PIN that sends the signal to measure feedback from capacitive sensors. const byte PIN_sensor_1 = 16; // PIN that measures capacitive sensor 1. const byte PIN_sensor_2 = 17; // PIN that measures capacitive sensor 2. const byte PIN_sensor_3 = 0; // PIN that measures capacitive sensor 3. const byte PIN_sensor_4 = 1; // PIN that measures capacitive sensor 4. const byte PIN_sensor_5 = 2; // PIN that measures capacitive sensor 5. const byte PIN_sensor_6 = 3; // PIN that measures capacitive sensor 6. const byte PIN_sensor_7 = 4; // PIN that measures capacitive sensor 7. // Analogic PIN : // N/A // I2C : const byte PIN_SDA = 17; const byte PIN_SCL = 18; // PWM : const byte PIN_RGB_LED_red = 5; // Pin associated to the red leg of the RGB LED. const byte PIN_RGB_LED_green = 9; // Pin associated to the green leg of the RGB LED. const byte PIN_RGB_LED_blue = 10; // Pin associated to the blue leg of the RGB LED. // ------------------------------------------------ // Other variables // ------------------------------------------------ // Puzzle 1 (capacitive sensors) : byte measured_sequence_sensors[sequence_length_sensors]; // sequence of sensor touches recorded. byte sequence_position_sensors = 0; // variable to determine in which position of the sequence a touch should be registered. long last_touch=0; // variable to determine when the last touch was detected. Used to reinitialize the sequence recorded after a certain amount of time byte correct_sequence_sensors=1; // variable to determine whether the sequence of touches recorded matches the expected sequence or not (1=OK, 2=KO). byte sequence_initialized_sensors=1; // variable used to control the touches sequence reinitialization. long total=0; // variable to measure the output from a capacitive sensor. byte puzzle_1_status = 0; // variable that indicates whether puzzle 1 has been solved (1) or not (0). Note : few seconds after solving the puzzle, this variable goes back to 0, to let the possibility to the players to solve the puzzle again. // Puzzle 2 (world map) : byte measured_sequence_world[sequence_length_world]; // sequence of connections recorded. byte sequence_position_world = 0; // variable to determine in which position of the sequence a connection should be registered. long last_connection_world=0; // variable to determine when the last connection was made. Used to reinitialize the sequence recorded after a certain amount of time. byte correct_sequence_world=0; // variable to determine whether the sequence of connections recorded matches the expected sequence or not (1=OK, 0=KO). byte sequence_initialized_world=1; // variable used to control the connections sequence reinitialization. byte input_measured_world=0; // variable to measure the input on each connection pin. byte puzzle_2_status = 0; // variable that indicates whether puzzle 2 has been solved (1) or not (0). Note : few seconds after solving the puzzle, this variable goes back to 0, to let the possibility to the players to solve the puzzle again. // Global : byte test_variable = 0; // ------------------------- // DECLARATION OF OBJECTS // ------------------------- // The copper plate I use presents 7 different cells (= sensors) : 1 is the top one, 2 is on its right side, etc going clockwise, ..., 7 is the center sensor. CapacitiveSensor cs_1 = CapacitiveSensor(PIN_sensor_emitter,PIN_sensor_1); // green wire (19/A5) CapacitiveSensor cs_2 = CapacitiveSensor(PIN_sensor_emitter,PIN_sensor_2); // black wire (3) CapacitiveSensor cs_3 = CapacitiveSensor(PIN_sensor_emitter,PIN_sensor_3); // blue wire (5) CapacitiveSensor cs_4 = CapacitiveSensor(PIN_sensor_emitter,PIN_sensor_4); // brown wire (A0/14) CapacitiveSensor cs_5 = CapacitiveSensor(PIN_sensor_emitter,PIN_sensor_5); // yellow wire (A4/18) CapacitiveSensor cs_6 = CapacitiveSensor(PIN_sensor_emitter,PIN_sensor_6); // red wire (A1/15) CapacitiveSensor cs_7 = CapacitiveSensor(PIN_sensor_emitter,PIN_sensor_7); // orange wire (A3/17) CapacitiveSensor cs_list[nb_sensors] = {cs_1, cs_2, cs_3, cs_4, cs_5, cs_6, cs_7}; // list of the capacitive sensors declared above, for code optimization. // ------------------------- // INITIALIZATION // ------------------------- // Setup code. Run once at power up, or each time the RESET button is pressed: void setup() { // ------------------------------------------------ // Communication // ------------------------------------------------ Wire.begin(i2c_daughter_board_address); // Starting the i2c bus as peripheral on address 9. // ------------------------------------------------ // Objects // ------------------------------------------------ // ------------------------------------------------ // Input / Output // ------------------------------------------------ pinMode(PIN_RGB_LED_red,OUTPUT); pinMode(PIN_RGB_LED_green,OUTPUT); pinMode(PIN_RGB_LED_blue,OUTPUT); for (byte i=0; i=DETECTION_THRESHOLD) && (sequence_position_sensors==0 || measured_sequence_sensors[sequence_position_sensors-1]!=i+1)){ // If allowing 2 consecutive touches on the same sensor : //if (total>=DETECTION_THRESHOLD){ set_color_by_name(BLUE); measured_sequence_sensors[sequence_position_sensors]=i+1; sequence_position_sensors=sequence_position_sensors+1; last_touch=millis(); sequence_initialized_sensors=0; delay(TIMER_BLINK); set_color_by_name(RGB_LED_OFF); break; } // end if } // end for // When a complete sequence of touches has been detected, a comparison with the expected sequence is performed : if (sequence_position_sensors==sequence_length_sensors){ for (byte i=0;i=TIMER_REINITIALIZATION) && (sequence_initialized_sensors==0))){ // Short LED orange blink to indicate reinitialization : if (sequence_position_sensors!=sequence_length_sensors){ set_color_by_name(WHITE); delay(TIMER_BLINK); set_color_by_name(RGB_LED_OFF); } // end if for (byte j=0;j=TIMER_REINITIALIZATION) && (sequence_initialized_world==0))){ // Short LED white blink to indicate reinitialization : if (sequence_position_world!=sequence_length_world){ set_color_by_name(WHITE); delay(TIMER_BLINK); set_color_by_name(RGB_LED_OFF); } // end if for (byte j=0;j