ESPMegaPRO-v3-SDK/ESPMegaPRO-IRKit-SDK/src/main.cpp

218 lines
6.1 KiB
C++

#include <ESPMegaProOS.hpp>
#include <IRReceiver.hpp>
/**
* @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);
}
}