Hi all,
I am building a heliostat with 300mm linear actuator control having potentiometer feedback (https://uk.rs-online.com/web/p/electric-linear-actuators/1774510), using a BNO055 IMU to give me the location and orientation of the elevation and azimuth angle of the mirror.
I am really lost as to how to control the linear actuator so that they move after they recieve data from the IMU.
Current normal is the current orientation and destination normal is the destination where the mirror needs to point.
My thought process goes like this: I've got the current normal vectors and from them I've calculated the destination normal vectors. Seems like a simple logic to move the linear actuators untill the Current IMU angle matches calculated anlge but I am unsure how to write that in code. How should I go about writing the code.
I've also attached the code I've written so far. Any advise will be greatly appreciated
#include <SolarPosition.h>
#include <DS3232RTC.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
uint16_t BNO055_SAMPLERATE_DELAY_MS = 100;
Adafruit_BNO055 myIMU = Adafruit_BNO055(55, 0x28);
// number of decimal digits to print
uint8_t digits = 3;
//AZIMUTH ACTUATOR
//const int ENA_PIN = 7; // the Arduino pin connected to the EN1 pin L298N
const int IN1_PIN = 6; // the Arduino pin connected to the IN1 pin L298N
const int IN2_PIN = 5; // the Arduino pin connected to the IN2 pin L298N
//ELEVATION ACTUATOR
//const int ENA_PIN = 8; // the Arduino pin connected to the EN2 pin L298N
const int IN3_PIN = 10; // the Arduino pin connected to the IN3 pin L298N
const int IN4_PIN = 9; // the Arduino pin connected to the IN4 pin L298N
// Initialising Variables-
float SunX; //sun vectors
float SunY;
float SunZ;
//You get the target vectors from another code called "Find_Target_WITH_LinearActuators".
//Input the target vectors manually in this code
float TargetX = 1.25; //target vector x
float TargetY = 2.34; //target vector y
float TargetZ = 5.11; //target vector z
//float dCNx, dCNy, dCNz; //euler degrees of current normal
//float vCNx, vCNy, vCNz; //vectors of the current normal
float DestinationNormalX; //this needs to be calculated from the sun and target vectors
float DestinationNormalY;
float DestinationNormalZ;
SolarPosition Loughborough(52.76336662631451, -1.2481144519918814); // Loughborough, UK
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
myIMU.begin();
SolarPosition::setTimeProvider(RTC.get);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.print("Loughborough: ");
SolarPosition(Loughborough.getSolarPosition(), digits);
delay(60000);
}
void SolarPosition(SolarPosition_t pos, int numDigits){
float sunEle = pos.elevation; //Sun Elevation Angle in Degrees
float sunAzt = pos.azimuth; //Sun Azimuth Angle in Degrees
Serial.print("elevation: ");
Serial.print(sunEle, numDigits);
Serial.print(" deg ");
Serial.print("azimuth: ");
Serial.print(sunAzt, numDigits);
Serial.println(" deg");
//Calculating Sun Vectors from the azimuth and elevation angles
float degToRadian = PI / 180.0; //converting degrees to radians
SunX = cos(sunEle * degToRadian) * cos((360 - sunAzt) * degToRadian); //Sun x coordinate
SunY = cos(sunEle * degToRadian) * sin((360 - sunAzt) * degToRadian); //Sun y coordinate
SunZ = sin(sunEle * degToRadian); //Sun z coordinate
//MATHS to calculate the destination normal vectors
float ax = SunX + TargetX;
float ay = SunY + TargetY;
float az = SunZ + TargetZ;
double denominator = sqrt((ax*ax) + (ay*ay) + (az*az));
DestinationNormalX = ax / denominator; //Destination normal vector x
DestinationNormalY = ay / denominator; //Destination normal vector y
DestinationNormalZ = az / denominator; //Destination normal vector z
Serial.print("Destination Normal X, Y, Z are ");
Serial.print(DestinationNormalX, 3);
Serial.print(DestinationNormalY, 3);
Serial.println(DestinationNormalZ, 3);
//CODE to find the current normal of the mirror
float dCNx, dCNy, dCNz; //euler degrees of current normal
imu::Vector<3> CurrentNormal = myIMU.getVector(Adafruit_BNO055::VECTOR_EULER);
Serial.print("Current normal Angles x, y, z are ");
Serial.print(dCNx = CurrentNormal.x()); //x euler angle in degress
Serial.print(", ");
Serial.print(dCNy = CurrentNormal.y()); //y euler angle in degress
Serial.print(", ");
Serial.print(dCNz = CurrentNormal.z()); //z euler angle in degress
Serial.println(" respectively.");
//the angles returned from the IMU are in degrees.
//we need to convert them to vectors to work with them
float vCNx, vCNy, vCNz; //vectors of the current normal
vCNx = cos(dCNx * degToRadian); //Current normal vector x
vCNy = cos(dCNy * degToRadian); //Current normal vector y
vCNz = cos(dCNz * degToRadian); //Current normal vector z
//Now we do some more maths to understand how much the linear actuator needs to move and then then we send the command to the linear actuator to move by that amount
//
//Now, we need to move the azimuth and elevation linear actuators accordingly
}



