Yes.
Part 1
#include "sdkconfig.h"
#include "esp_system.h" //This inclusion configures the peripherals in the ESP system.
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include <SimpleKalmanFilter.h>
#include <driver/adc.h>
#include "esp_sleep.h"
#include "driver/mcpwm.h"
const int TaskCore1 = 1;
const int TaskCore0 = 0;
const int TaskStack20K = 20000;
const int Priority3 = 3;
const int Priority4 = 4;
volatile bool EnableTracking = true;
////
void setup()
{
// set up A:D channels
adc_power_on( );
vTaskDelay( 1 );
adc1_config_width(ADC_WIDTH_12Bit);
// ADC1 channel 0 is GPIO36 (ESP32), GPIO1 (ESP32-S2)
adc1_config_channel_atten(ADC1_CHANNEL_0 , ADC_ATTEN_DB_11); // azimuth 0
// // ADC1_CHANNEL_3 ADC1 channel 3 is GPIO39 (ESP32)
adc1_config_channel_atten(ADC1_CHANNEL_3, ADC_ATTEN_DB_11); // azimuth 1
// // ADC1 channel 5 is GPIO33
adc1_config_channel_atten(ADC1_CHANNEL_5, ADC_ATTEN_DB_11); // altitude 1
// // ADC1 channel 6 is GPIO34
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11); // altitude 0
// // adc for light dark detection, ADC1 channel 7 is GPIO35 (ESP32)
adc1_config_channel_atten(ADC1_CHANNEL_7, ADC_ATTEN_DB_11);
// control for relay to supply power to the servos
pinMode( 5, OUTPUT );
vTaskDelay(1);
//
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM1A, GPIO_NUM_4 ); // Azimuth
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, GPIO_NUM_12 ); // Altitude servo
//
mcpwm_config_t pwm_config = {};
pwm_config.frequency = 50; //frequency = 50Hz, i.e. for every servo motor time period should be 20ms
pwm_config.cmpr_a = 0; //duty cycle of PWMxA = 0
pwm_config.cmpr_b = 0; //duty cycle of PWMxb = 0
pwm_config.counter_mode = MCPWM_UP_COUNTER;
pwm_config.duty_mode = MCPWM_DUTY_MODE_0;
//
//
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config); //Configure PWM0A timer 0 with above settings
mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_1, &pwm_config); //Configure PWM0A timer 1 with above settings
// ////
fMoveAltitude( 1500 );
fMoveAzimuth( 900 );
////
xTaskCreatePinnedToCore( TrackSun, "TrackSun", TaskStack20K, NULL, Priority3, NULL, TaskCore1 ); // assigned to core
xTaskCreatePinnedToCore( fDaylight, "fDaylight", TaskStack20K, NULL, Priority3, NULL, TaskCore0 ); // assigned to core
//// // esp_sleep_enable_timer_wakeup( (60000000 * 2) ); // set timer to wake up once a minute 60000000uS
}
//
void fDaylight( void * pvParameters )
{
int lightLevel = 0;
while (1)
{
lightLevel = adc1_get_raw(ADC1_CHANNEL_7);
if ( adc1_get_raw(ADC1_CHANNEL_7) <= 300 )
{
// if light level to low park boom
fMoveAltitude( 1475 );
vTaskDelay( 30 );
fMoveAzimuth( 2000 );
vTaskDelay( 25 );
// put esp32 into deep sleep
EnableTracking = false;
digitalWrite( 5, HIGH ); // remove power from relay module.
vTaskDelay( 1 );
esp_sleep_enable_timer_wakeup( (60000000 * 2) ); // set timer to wake up once a minute 60000000uS
esp_deep_sleep_start();
} else {
digitalWrite( 5, LOW ); // energize servo motors
EnableTracking = true;
}
vTaskDelay( 1000 );
} // while(1)
} // void fDaylight( void * pvParameters )
////
void mcpwm_gpio_initialize(void)
{
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM1A, GPIO_NUM_4 );
mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, GPIO_NUM_12 );
}
////
// void TrackSun( int Altitude, int Azimuth )
void TrackSun( void * pvParameters )
{
int64_t EndTime = esp_timer_get_time();
int64_t StartTime = esp_timer_get_time(); //gets time in uSeconds like Arduino Micros
int Altitude = 1500;
int Azimuth = 900;
int maxAltitudeRange = 2144;
int minAltitudeRange = 900;
int maxAzimuthRange = 2144;
int minAzimuthRange = 900;
float AltitudeThreashold = 10.0f;
float AzimuthThreashold = 10.0f;
float kalmanThreshold = 80.0f;
SimpleKalmanFilter kfAltitude0( AltitudeThreashold, kalmanThreshold, .01 ); // kalman filter Altitude 0
SimpleKalmanFilter kfAltitude1( AltitudeThreashold, kalmanThreshold, .01 ); // kalman filter Altitude 1
SimpleKalmanFilter kfAzimuth0( AzimuthThreashold, kalmanThreshold, .01 ); // kalman filter Azimuth 0
SimpleKalmanFilter kfAzimuth1( AzimuthThreashold, kalmanThreshold, .01 ); // kalman filter Azimuth 1
float filteredAltitude_0 = 0.0f;
float filteredAltitude_1 = 0.0f;
float filteredAzimuth_0 = 0.0f;
float filteredAzimuth_1 = 0.0f;
uint64_t AzimuthEndTime = esp_timer_get_time();
uint64_t AzimuthStartTime = esp_timer_get_time(); //gets time in uSeconds like Arduino Micros,
uint64_t AltitudeEndTime = esp_timer_get_time();
uint64_t AltitudeStartTime = esp_timer_get_time(); //gets time in uSeconds like Arduino Micros,
int StartupCount = 0;
int TorqueAmmount = 5;
while (1)
{
if ( EnableTracking )
{
//Altitude
AltitudeEndTime = esp_timer_get_time() - AltitudeStartTime; // produce elasped time for the simpleKalmanFilter
kfAltitude0.setProcessNoise( float(AltitudeEndTime) / 1000000.0f );
kfAltitude1.setProcessNoise( float(AltitudeEndTime) / 1000000.0f );
filteredAltitude_0 = kfAltitude0.updateEstimate( (float)adc1_get_raw(ADC1_CHANNEL_6) );
filteredAltitude_1 = kfAltitude1.updateEstimate( (float)adc1_get_raw(ADC1_CHANNEL_5) );
if ( (filteredAltitude_0 > filteredAltitude_1) && (abs(filteredAltitude_0 - filteredAltitude_1) > AltitudeThreashold))
{
Altitude -= TorqueAmmount;
if ( Altitude < minAltitudeRange )
{
Altitude = 900;
}
fMoveAltitude( Altitude );
AltitudeStartTime = float(esp_timer_get_time());
}
if ( (filteredAltitude_0 < filteredAltitude_1) && (abs(filteredAltitude_0 - filteredAltitude_1) > AltitudeThreashold) )
{
Altitude += TorqueAmmount;
if ( Altitude >= maxAltitudeRange )
{
Altitude = 900;
}
fMoveAltitude( Altitude );
AltitudeStartTime = esp_timer_get_time();
}
////
There are 2 main tasks that run in a loop on its own core. With the proper hardware what you ask is quite possible.