Code: Select all
/*
Project, use solar cells to generate power
2/2/2020
*/
#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 "freertos/event_groups.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;
const int SerialDataBits = 115200;
volatile bool EnableTracking = true;
////
void setup()
{
Serial.begin( 115200 );
// 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);
Serial.println( adc1_get_raw(ADC1_CHANNEL_7) );
if ( adc1_get_raw(ADC1_CHANNEL_7) <= 300 )
{
fMoveAltitude( 1475 );
fMoveAzimuth( 2000 );
vTaskDelay( 25 );
// put esp32 into light 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 = 80.0f;
float kalmanThreshold = 15.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();
}
//// AZIMUTH
AzimuthEndTime = esp_timer_get_time() - AzimuthStartTime; // produce elasped time for the simpleKalmanFilter
kfAzimuth0.setProcessNoise( float(AzimuthEndTime) / 1000000.0f ); //convert time of process to uS, update SimpleKalmanFilter q
kfAzimuth1.setProcessNoise( float(AzimuthEndTime) / 1000000.0f ); //convert time of process to uS, update SimpleKalmanFilter q
filteredAzimuth_0 = kfAzimuth0.updateEstimate( (float)adc1_get_raw(ADC1_CHANNEL_3) );
filteredAzimuth_1 = kfAzimuth1.updateEstimate( (float)adc1_get_raw(ADC1_CHANNEL_0) );
if ( (filteredAzimuth_0 > filteredAzimuth_1) && (abs(filteredAzimuth_0 - filteredAzimuth_1)) > AzimuthThreashold )
{
Azimuth += TorqueAmmount;
if ( Azimuth >= maxAzimuthRange )
{
Azimuth = 900;
}
fMoveAzimuth( Azimuth );
Serial.print( " AltI > " );
Serial.println( Altitude );
AzimuthStartTime = esp_timer_get_time();
}
if ( (filteredAzimuth_0 < filteredAzimuth_1) && (abs(filteredAzimuth_1 - filteredAzimuth_0)) > AzimuthThreashold )
{
Azimuth -= TorqueAmmount;
if ( (Azimuth >= maxAzimuthRange) || (Azimuth <= minAzimuthRange) )
{
Azimuth = 900;
}
fMoveAzimuth( Azimuth );
AzimuthStartTime = esp_timer_get_time();
} //azmiuth end
if ( StartupCount < 500 )
{
++StartupCount;
// Serial.println( StartupCount );
} else {
TorqueAmmount = 1;
esp_sleep_enable_timer_wakeup( (60000000 / 20) ); // set timer to wake up
esp_light_sleep_start();
}
}
} // while(1)
} //void TrackSun()
////
void fMoveAltitude( int MoveTo )
{
mcpwm_set_duty_in_us(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_A, MoveTo);
vTaskDelay( 12 );
}
//////
void fMoveAzimuth( int MoveTo )
{
mcpwm_set_duty_in_us(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_A, MoveTo);
vTaskDelay( 12 );
}
////
void loop() {}
////
I had thought the MCPWM would remain on during light sleet but sometimes it seems to no longer provide a torque value to hold position during light sleep.
Is there a way to set or make the MCPWM stay on during light sleep?