Hi all,
I am creating a heliostat user interface with pushbuttons. The code has different functions (). I want to control each of the functions with pushbuttons, so when user presses button 1 execute HeliostatTracking() function, button 2 CaptureTarget. Could you please assist as to how to write that code. With the HeliostatTracking function, I want the code to run infinately until the user presses any other button. How do I do that.
/*
Update from Code V3 is that this code has the limits of the sun position because we don't want the heliostat to be turned on throughout the night.
Use of functions to move the linear actuators.
We only want it on when the sun elevation is greater than 5 and azimuth must be from dawn to dusk.
*/
#include <SolarPosition.h> //Sun position library to get sun azimuth and elevation angle
#include <DS3232RTC.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
Adafruit_BNO055 myIMU = Adafruit_BNO055(-1, 0x28);
// number of decimal digits to print
uint8_t digits = 3;
//Linear actuator variable declaration
int speedLA = 150;
const int ENA_PIN = 6; // the Arduino pin connected to the EN1 pin L298N
const int IN1_PIN = 7; // the Arduino pin connected to the IN1 pin L298N
const int IN2_PIN = 8; // the Arduino pin connected to the IN2 pin L298N
const int ENB_PIN = 11; // the Arduino pin connected to the EN1 pin L298N
const int IN3_PIN = 9; // the Arduino pin connected to the IN3 pin L298N
const int IN4_PIN = 10; // the Arduino pin connected to the IN4 pin L298N
int LedAzt = 3;
int LedEle = 5;
volatile float sunEle;
volatile float sunAzt;
float TargetAzimuth;
float TargetElevation;
//these need to be calculated from the sun and target azimuth and elevation angles
float DN_Azimuth; //destination normal azimuth angle
float DN_Elevation; //destination normal elevation angle
SolarPosition Loughborough(52.76336662631451, -1.2481144519918814); // Loughborough, UK
void setup() {
Serial.begin(115200);
pinMode(LedAzt, OUTPUT);
pinMode(LedEle, OUTPUT);
SolarPosition::setTimeProvider(RTC.get); //Using the RTC to get the current time
//********LINEAR ACTUATOR SET UP*********
pinMode(ENA_PIN, OUTPUT);
pinMode(IN1_PIN, OUTPUT);
pinMode(IN2_PIN, OUTPUT);
pinMode(IN3_PIN, OUTPUT);
pinMode(IN4_PIN, OUTPUT);
pinMode(ENB_PIN, OUTPUT);
analogWrite(ENA_PIN, speedLA);
analogWrite(ENB_PIN, speedLA);
//*******IMU SETUP CODE********************************
Serial.println("Starting IMU....."); Serial.println("");
/* Initialise the sensor */
if(!myIMU.begin())
{
/* There was a problem detecting the BNO055 ... check your connections */
Serial.print("Ooops, no IMU detected ... Check your wiring or I2C ADDR!");
while(1);
}
delay(1000);
myIMU.setExtCrystalUse(true);
Serial.println("Calibration status values: 0=uncalibrated, 3=fully calibrated");
//**********************************************************
}
void loop() {
//*******IMU calibration***************
uint8_t system, gyro, accel, mag = 0;
myIMU.getCalibration(&system, &gyro, &accel, &mag);
Serial.println("");
Serial.print("CALIBRATION: Sys=");
Serial.print(system, DEC);
Serial.print(" Gyro=");
Serial.print(gyro, DEC);
Serial.print(" Accel=");
Serial.print(accel, DEC);
Serial.print(" Mag=");
Serial.println(mag, DEC);
MoveHeliostat();
CaptureTarget(TargetAzimuth, TargetElevation);
SolarPosition(Loughborough.getSolarPosition(), digits); //Get the Sun Azimuth and Elevation angles and return the destination normal angles
HeliostatTracking();
}
void MoveHeliostat(){
while(Serial.available()>0) // if there is data comming
{
int motion = Serial.parseInt(); //Serial.parseInt() for serial monitor interface, Serial.read() for bluetooth
Serial.print("data received ");
Serial.println(motion);
if(motion == 1){
// extend the azimuth actuator
digitalWrite(IN1_PIN, HIGH);
digitalWrite(IN2_PIN, LOW);
Serial.println("Extending Azimuth");
}
if (motion == 2){
// retract the azimuth actuator
digitalWrite(IN1_PIN, LOW);
digitalWrite(IN2_PIN, HIGH);
Serial.println("Retracting Azimuth");
}
if (motion == 3){
// stop the azimuth actuator
digitalWrite(IN1_PIN, LOW);
digitalWrite(IN2_PIN, LOW);
Serial.println("Stopped Azimuth");
}
if(motion == 6){
// extend the ELEVATION actuator
digitalWrite(IN3_PIN, HIGH);
digitalWrite(IN4_PIN, LOW);
Serial.println("Extending Elevation");
}
if (motion == 7){
// retract the ELEVATION actuator
digitalWrite(IN3_PIN, LOW);
digitalWrite(IN4_PIN, HIGH);
Serial.println("Retracting Elevation");
}
if (motion == 8){
// stop the ELEVATION actuator
digitalWrite(IN3_PIN, LOW);
digitalWrite(IN4_PIN, LOW);
Serial.println("Stopped Elevation");
}
}
}
void CaptureTarget(float tazt, float tele){
imu::Vector<3> TargetEulerAngle = myIMU.getVector(Adafruit_BNO055::VECTOR_EULER);
Serial.print("Angle x, y, z are ");
Serial.print(tazt = TargetEulerAngle.x());
Serial.print(", ");
Serial.print(tele = 90 - TargetEulerAngle.z());
Serial.println(" respectively.");
return tazt, tele;
}
void HeliostatTracking(){
//******CODE to find the CURRENT Azimuth and Elevation angles of the mirror********
float CN_Azimuth, CN_Elevation; //euler degrees of current normal
imu::Vector<3> CurrentNormal = myIMU.getVector(Adafruit_BNO055::VECTOR_EULER);
Serial.print("Current Azimuth ");
Serial.print(CN_Azimuth = CurrentNormal.x()); //Current Normal Azimuth angle, x euler angle in degress
Serial.print("\t\tCurrent Elevation ");
Serial.println(CN_Elevation = 90 - CurrentNormal.z()); //Current Normal Elevation angle, z euler angle in degress; (90 - Current Normal ) because we are changing the elevation angle plane to be the plane of the mirror
//*******Now we need to move the linear actuators accordingly***************************
if (sunEle >4 && sunAzt > 110 && sunAzt < 250){ //perform the following code only when the sun position is high enough in the sky
//the reason the angles are rounded is because it is very difficult for the Destination normal value (till 2 decimal places) to be equal to the Current Normal Value
//this gives us an error +/- 1 degree.
if(round(DN_Azimuth) > round(CN_Azimuth)){ //if the Destination Azimuth is greater than Current Azimuth retract the azimuth linear actuator
//retract Azimuth linear actuator
RetractAzimuth();
digitalWrite(LedAzt, HIGH); //LED is lit up to indicate that the destination azimuth is greater than the current azimuth
}
else if (round(DN_Azimuth) < round(CN_Azimuth)){
//extend Azimuth linear actuator
ExtendAzimuth();
analogWrite(LedAzt, 50); //LED brightness reduces to indicate that the destination azimuth is less than the current azimuth
}
else{
//stop azimuth linear actuator and pause program for 2 seconds for example. Experimentally determine later if you want to increase the time. THis causes the sun to move enough for the next reading.
StopAzimuth();
digitalWrite(LedAzt, LOW); //LED is turned off indicate that the destination azimuth is equal to the current azimuth and hence the mirror has reached the correct orientation
delay(200);
}
//Now, we need to move the elevation linear actuator accordingly
if(round(DN_Elevation) > round(CN_Elevation)){ //if the Destination Elevation is greater than Current Elevation retract the elevation linear actuator
//retract elevation linear actuator
RetractElevation();
digitalWrite(LedEle, HIGH); //LED is lit up to indicate that the destination elevation is greater than the current elevation
}
else if (round(DN_Elevation) < round(CN_Elevation)){
//extend elevation linear actuator
ExtendElevation();
analogWrite(LedEle, 50); //LED brightness reduces to indicate that the destination elevation is less than the current elevation
}
else{
//stop elevation linear actuator and pause program for 2 milliseconds for example. Experimentally determine later if you want to increase the time. THis causes the sun to move enough for the next reading.
StopElevation();
digitalWrite(LedEle, LOW); //LED is turned off indicating that the destination elevation is equal to the current elevation and hence the mirror has reached the correct elevation angle
delay(200);
}
if(round(DN_Azimuth) == round(CN_Azimuth) && round(DN_Elevation) == round(CN_Elevation)){
Serial.print("Error Azimuth = "); Serial.print(abs(DN_Azimuth-CN_Azimuth));
Serial.print("\t Error Elevation = "); Serial.println(abs(DN_Elevation-CN_Elevation));
delay(60000);
}
delay(100);
}
}
void SolarPosition(SolarPosition_t pos, int numDigits){
//*******Calculating the SUN azimuth and elevation angle********
sunEle = pos.elevation; //Sun Elevation Angle in Degrees
sunAzt = pos.azimuth; //Sun Azimuth Angle in Degrees
Serial.println("Loughborough ");
Serial.print("Sun Azimuth: ");
Serial.print(sunAzt, numDigits);
Serial.print(" deg");
Serial.print("\tSun Elevation: ");
Serial.print(sunEle, numDigits);
Serial.println(" deg ");
//********CODE to calculate the Destination Azimuth and Elevation******************
DN_Azimuth = (sunAzt + TargetAzimuth ) / 2 ; //Midpoint azimuth
DN_Elevation =(sunEle + TargetElevation) / 2 ; //Midpoint Elevation
Serial.print("Destination Azimuth ");
Serial.print(DN_Azimuth);
Serial.print("\tDestination Elevation ");
Serial.println(DN_Elevation);
}
//Useful Functions
void ExtendAzimuth(){
digitalWrite(IN1_PIN, HIGH);
digitalWrite(IN2_PIN, LOW);
}
void RetractAzimuth(){
digitalWrite(IN1_PIN, LOW);
digitalWrite(IN2_PIN, HIGH);
}
void StopAzimuth(){
digitalWrite(IN1_PIN, LOW);
digitalWrite(IN2_PIN, LOW);
}
void ExtendElevation(){
digitalWrite(IN3_PIN, HIGH);
digitalWrite(IN4_PIN, LOW);
}
void RetractElevation(){
digitalWrite(IN3_PIN, LOW);
digitalWrite(IN4_PIN, HIGH);
}
void StopElevation(){
digitalWrite(IN3_PIN, LOW);
digitalWrite(IN4_PIN, LOW);
}