#include #include /** * @brief This program helps construct an ir timing table for a air conditioner * * Each run of this program will generate a new table, for a specific mode and fan speed * It will iterate through all the temperature settings, and record the timing for each temperature * It will then print the timing table as a C++ 2D array, which can be copied into your main program * The first dimension is the temperature, the second dimension is the timing */ #define min_temp 16 #define max_temp 32 #define MAX_TIMINGS 1000 // 1000 timings should be enough for any remote #define CAPTURE_TIMEOUT 5 // seconds uint32_t timings[max_temp - min_temp + 1][MAX_TIMINGS] = {0}; uint16_t timings_count[max_temp - min_temp + 1] = {0}; ESPMegaPRO espmega = ESPMegaPRO(); void beginRoutine() { Serial.println("Beginning IR capture routine"); for (int i = min_temp; i <= max_temp; i++) { Serial.printf("Please press the button on your remote for %d degrees\n", i); IRReceiver::start_long_receive(); for (int i = 0; i < CAPTURE_TIMEOUT; i++) { Serial.printf("Waiting for IR signal... (%d seconds left)\n", CAPTURE_TIMEOUT - i); // During this period, if the user press any key, the routine will be restarted // Unless it is a space bar, which will be used to confirm the timings if (Serial.available()) { char c = Serial.read(); if (c != ' ') { Serial.println("User interrupted, restarting routine..."); return; } } vTaskDelay(1000 / portTICK_PERIOD_MS); } ir_data_t data = IRReceiver::end_long_receive(); // Retry if no data was received if (data.size == 0) { Serial.println("No data received, retrying..."); i--; continue; } // Remove last timing data.size--; Serial.printf("Received timing of size %d\n", data.size); // Print out the timing array for (int i = 0; i < data.size; i++) { Serial.printf("%u%s", data.data[i], i == data.size - 1 ? "\n" : ", "); } // If any timings exceed 20000, print a warning for (int i = 0; i < data.size; i++) { if (data.data[i] > 50000U) { Serial.println("WARNING: Timing exceeds 50000, Possible data corruption!"); break; } } // Ask the user if the timings are correct Serial.println("Are the timings correct? (y/n)"); // Flush the serial buffer while (Serial.available()) { Serial.read(); } // Wait for user input while (!Serial.available()) { vTaskDelay(100 / portTICK_PERIOD_MS); } char c = Serial.read(); if (c != 'y') { Serial.println("Retrying..."); i--; continue; } // Store the timings count timings_count[i - min_temp] = data.size; // Copy the timings into the timings array memcpy(timings[i - min_temp], data.data, sizeof(uint32_t) * data.size); free(data.data); } Serial.println("Generating C++ code for the timings, please wait..."); // Find the maximum number of timings int max_timings = 0; for (int i = 0; i < max_temp - min_temp + 1; i++) { if (timings_count[i] > max_timings) { max_timings = timings_count[i]; } } // Print the timings Serial.println("Done!, please copy the following into your main program"); Serial.printf("uint16_t timings[%d][%d] = {\n", max_temp - min_temp + 1, max_timings); for (int i = 0; i < max_temp - min_temp + 1; i++) { Serial.printf(" {"); for (int j = 0; j < timings_count[i]; j++) { Serial.printf("%u%s", timings[i][j], j == timings_count[i] - 1 ? "" : ", "); } Serial.println(i == max_temp - min_temp ? "}" : "},"); } Serial.println("};"); Serial.println("Stopping IR capture routine"); Serial.printf("IR Capture routine finished\n"); } void capture_single() { Serial.println("Please press the button on your remote"); IRReceiver::start_long_receive(); for (int i = 0; i < CAPTURE_TIMEOUT; i++) { Serial.printf("Waiting for IR signal... (%d seconds left)\n", CAPTURE_TIMEOUT - i); vTaskDelay(1000 / portTICK_PERIOD_MS); } ir_data_t data = IRReceiver::end_long_receive(); // Remove last timing data.size--; Serial.printf("Received timing of size %d\n", data.size); // If any timings exceed 20000, print a warning for (int i = 0; i < data.size; i++) { if (data.data[i] > 50000U) { Serial.println("WARNING: Timing exceeds 50000, Possible data corruption!"); break; } } if (data.size == 0) { Serial.println("No data received, retrying..."); capture_single(); return; } // Print the timings Serial.println("Done!, please copy the following into your main program"); Serial.printf("uint32_t timings[%d] = {", data.size); for (int i = 0; i < data.size; i++) { Serial.printf("%u%s", data.data[i], i == data.size - 1 ? "" : ", "); } Serial.println("};"); free(data.data); Serial.println("Do you want to capture another signal? (y/n)"); // Flush the serial buffer while (Serial.available()) { Serial.read(); } // Wait for user input while (!Serial.available()) { vTaskDelay(100 / portTICK_PERIOD_MS); } char c = Serial.read(); if (c == 'y') { capture_single(); } } void menu_init() { // Print the menu // The menu will have 2 options, one to start the routine, and one capture a single IR signal Serial.println("ESPMegaPRO IR Development Kit - IR Capture"); Serial.println("1. Begin IR Capture Routine"); Serial.println("2. Capture Single IR Signal"); Serial.println("Please select an option:"); // Wait for user input while (!Serial.available()) { vTaskDelay(100 / portTICK_PERIOD_MS); } char c = Serial.read(); // Start the routine if (c == '1') { beginRoutine(); } // Capture a single IR signal else if (c == '2') { capture_single(); } } void setup() { IRReceiver::begin(36); espmega.begin(); } void loop() { menu_init(); Serial.println("Press any key to return to the main menu"); while (!Serial.available()) { vTaskDelay(100 / portTICK_PERIOD_MS); } }