angle control on elevation axis for dual axis solar tracker

I found this video it has the code below:

////
//THIS IS A DEMO SOFTWARE JUST FOR EXPERIMENT PURPOSES IN A NONCOMMERCIAL ACTIVITY
//Version: 1.0 (AUG, 2016)

//Gyro - Arduino UNO R3
//VCC  -  5V
//GND  -  GND
//SDA  -  A4
//SCL  -  A5
//INT - port-2

#include <Wire.h>
//Declaring some global variables
int gyro_x, gyro_y, gyro_z;
long gyro_x_cal, gyro_y_cal, gyro_z_cal;
boolean set_gyro_angles;

long acc_x, acc_y, acc_z, acc_total_vector;
float angle_roll_acc, angle_pitch_acc;

float angle_pitch, angle_roll;
int angle_pitch_buffer, angle_roll_buffer;
float angle_pitch_output, angle_roll_output;

long loop_timer;
int temp;

void setup() {
  Wire.begin();                                                        //Start I2C as master
  setup_mpu_6050_registers();                                          //Setup the registers of the MPU-6050 
  for (int cal_int = 0; cal_int < 1000 ; cal_int ++){                  //Read the raw acc and gyro data from the MPU-6050 for 1000 times
    read_mpu_6050_data();                                             
    gyro_x_cal += gyro_x;                                              //Add the gyro x offset to the gyro_x_cal variable
    gyro_y_cal += gyro_y;                                              //Add the gyro y offset to the gyro_y_cal variable
    gyro_z_cal += gyro_z;                                              //Add the gyro z offset to the gyro_z_cal variable
    delay(3);                                                          //Delay 3us to have 250Hz for-loop
  }

  // divide by 1000 to get avarage offset
  gyro_x_cal /= 1000;                                                 
  gyro_y_cal /= 1000;                                                 
  gyro_z_cal /= 1000;                                                 
  Serial.begin(115200);
  loop_timer = micros();                                               //Reset the loop timer
}

void loop(){

  read_mpu_6050_data();   
 //Subtract the offset values from the raw gyro values
  gyro_x -= gyro_x_cal;                                                
  gyro_y -= gyro_y_cal;                                                
  gyro_z -= gyro_z_cal;                                                
         
  //Gyro angle calculations . Note 0.0000611 = 1 / (250Hz x 65.5)
  angle_pitch += gyro_x * 0.0000611;                                   //Calculate the traveled pitch angle and add this to the angle_pitch variable
  angle_roll += gyro_y * 0.0000611;                                    //Calculate the traveled roll angle and add this to the angle_roll variable
  //0.000001066 = 0.0000611 * (3.142(PI) / 180degr) The Arduino sin function is in radians
  angle_pitch += angle_roll * sin(gyro_z * 0.000001066);               //If the IMU has yawed transfer the roll angle to the pitch angel
  angle_roll -= angle_pitch * sin(gyro_z * 0.000001066);               //If the IMU has yawed transfer the pitch angle to the roll angel
  
  //Accelerometer angle calculations
  acc_total_vector = sqrt((acc_x*acc_x)+(acc_y*acc_y)+(acc_z*acc_z));  //Calculate the total accelerometer vector
  //57.296 = 1 / (3.142 / 180) The Arduino asin function is in radians
  angle_pitch_acc = asin((float)acc_y/acc_total_vector)* 57.296;       //Calculate the pitch angle
  angle_roll_acc = asin((float)acc_x/acc_total_vector)* -57.296;       //Calculate the roll angle
  
  angle_pitch_acc -= 0.0;                                              //Accelerometer calibration value for pitch
  angle_roll_acc -= 0.0;                                               //Accelerometer calibration value for roll

  if(set_gyro_angles){                                                 //If the IMU is already started
    angle_pitch = angle_pitch * 0.9996 + angle_pitch_acc * 0.0004;     //Correct the drift of the gyro pitch angle with the accelerometer pitch angle
    angle_roll = angle_roll * 0.9996 + angle_roll_acc * 0.0004;        //Correct the drift of the gyro roll angle with the accelerometer roll angle
  }
  else{                                                                //At first start
    angle_pitch = angle_pitch_acc;                                     //Set the gyro pitch angle equal to the accelerometer pitch angle 
    angle_roll = angle_roll_acc;                                       //Set the gyro roll angle equal to the accelerometer roll angle 
    set_gyro_angles = true;                                            //Set the IMU started flag
  }
  
  //To dampen the pitch and roll angles a complementary filter is used
  angle_pitch_output = angle_pitch_output * 0.9 + angle_pitch * 0.1;   //Take 90% of the output pitch value and add 10% of the raw pitch value
  angle_roll_output = angle_roll_output * 0.9 + angle_roll * 0.1;      //Take 90% of the output roll value and add 10% of the raw roll value
  Serial.print(" |Pitch Angle  = "); Serial.println(angle_pitch_output);
  Serial.print(" |Roll Angle  = "); Serial.println(angle_roll_output);
  
 while(micros() - loop_timer < 4000);                                 //Wait until the loop_timer reaches 4000us (250Hz) before starting the next loop
 loop_timer = micros();//Reset the loop timer
  
}




void setup_mpu_6050_registers(){
  //Activate the MPU-6050
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
  Wire.write(0x6B);                                                    //Send the requested starting register
  Wire.write(0x00);                                                    //Set the requested starting register
  Wire.endTransmission();                                             
  //Configure the accelerometer (+/-8g)
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
  Wire.write(0x1C);                                                    //Send the requested starting register
  Wire.write(0x10);                                                    //Set the requested starting register
  Wire.endTransmission();                                             
  //Configure the gyro (500dps full scale)
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
  Wire.write(0x1B);                                                    //Send the requested starting register
  Wire.write(0x08);                                                    //Set the requested starting register
  Wire.endTransmission();                                             
}


void read_mpu_6050_data(){                                             //Subroutine for reading the raw gyro and accelerometer data
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
  Wire.write(0x3B);                                                    //Send the requested starting register
  Wire.endTransmission();                                              //End the transmission
  Wire.requestFrom(0x68,14);                                           //Request 14 bytes from the MPU-6050
  while(Wire.available() < 14);                                        //Wait until all the bytes are received
  acc_x = Wire.read()<<8|Wire.read();                                  
  acc_y = Wire.read()<<8|Wire.read();                                  
  acc_z = Wire.read()<<8|Wire.read();                                  
  temp = Wire.read()<<8|Wire.read();                                   
  gyro_x = Wire.read()<<8|Wire.read();                                 
  gyro_y = Wire.read()<<8|Wire.read();                                 
  gyro_z = Wire.read()<<8|Wire.read();                                 
}

I implemented it into my code.
What I'm stuck at is I was able to get the angle output to display in the code below. However the numbers that are printed aren't right.

It seems I can't use the HC12 module at 115200 bps as the baud rate.
The MPU 6050 is running at this rate in the code above I think because it displays the proper angle due to the smoothing and calibration that is occurring. If I run it at 9600 bps the values don't update properly.

I integrated the code above into my dual axis solar tracking below.
I don't need precision on the decimal point level for elevation angle control.
I am using the MPU6050 as an angle limit switch where the solar panel/cooker stops rotating if it's beyond a certain tilt angle.

These are the printed values I'm getting from the code below:
The angle value should be like 60 to 90 degrees
but all I get is .xx to .xx as values.

Any ideas on how I can simplify the code?
All I need to do is calculate elevation angle properly(Serial.print(angle_roll_output)?

<28,84,47,76,10000,5,-0.17>
<63,58,73,40,10000,5,-0.32>
<40,105,51,88,10000,5,-0.58>
#include <Wire.h>
int gyro_x, gyro_y, gyro_z;
long gyro_x_cal, gyro_y_cal, gyro_z_cal;
boolean set_gyro_angles;

long acc_x, acc_y, acc_z, acc_total_vector;
float angle_roll_acc, angle_pitch_acc;

float angle_pitch, angle_roll;
int angle_pitch_buffer, angle_roll_buffer;
float angle_pitch_output, angle_roll_output;

long loop_timer;
int temp;

#include <SoftwareSerial.h>
SoftwareSerial HC12(11,10); // (HC-12 TX Pin, HC-12 RX)

const int sensorPinTL = A0;  
const int sensorPinBL = A1;
const int sensorPinTR = A2;  
const int sensorPinBR = A3;  

// The sensor value
int TL = 0; 
int BL = 0;
int TR = 0;         
int BR = 0;

// Minimum sensor value, more light is seen
int sensorMinTL = 0; 
int sensorMinBL = 0;
int sensorMinTR = 0;        
int sensorMinBR = 0;

int sensorMaxTL = 1023; 
int sensorMaxBL = 1023; 
int sensorMaxTR = 1023;           
int sensorMaxBR = 1023; 

void setup() {
  Serial.begin(9600);
  HC12.begin(9600); //serial port to HC12

  Wire.begin();                                                        //Start I2C as master
  setup_mpu_6050_registers();                                          //Setup the registers of the MPU-6050 
  for (int cal_int = 0; cal_int < 1000 ; cal_int ++){                  //Read the raw acc and gyro data from the MPU-6050 for 1000 times
    read_mpu_6050_data();                                             
    gyro_x_cal += gyro_x;                                              //Add the gyro x offset to the gyro_x_cal variable
    gyro_y_cal += gyro_y;                                              //Add the gyro y offset to the gyro_y_cal variable
    gyro_z_cal += gyro_z;                                              //Add the gyro z offset to the gyro_z_cal variable
    delay(3);                                                          //Delay 3us to have 250Hz for-loop
  }

  // divide by 1000 to get average offset
  gyro_x_cal /= 1000;                                                 
  gyro_y_cal /= 1000;                                                 
  gyro_z_cal /= 1000;                                                 
  //Serial.begin(115200);
  loop_timer = micros();                                               //Reset the loop timer
}

void loop() {

  read_mpu_6050_data();   
 //Subtract the offset values from the raw gyro values
  gyro_x -= gyro_x_cal;                                                
  gyro_y -= gyro_y_cal;                                                
  gyro_z -= gyro_z_cal;                                                
         
  //Gyro angle calculations . Note 0.0000611 = 1 / (250Hz x 65.5)
  angle_pitch += gyro_x * 0.0000611;                                   //Calculate the traveled pitch angle and add this to the angle_pitch variable
  angle_roll += gyro_y * 0.0000611;                                    //Calculate the traveled roll angle and add this to the angle_roll variable
  //0.000001066 = 0.0000611 * (3.142(PI) / 180degr) The Arduino sin function is in radians
  angle_pitch += angle_roll * sin(gyro_z * 0.000001066);               //If the IMU has yawed transfer the roll angle to the pitch angel
  angle_roll -= angle_pitch * sin(gyro_z * 0.000001066);               //If the IMU has yawed transfer the pitch angle to the roll angel
  
  //Accelerometer angle calculations
  acc_total_vector = sqrt((acc_x*acc_x)+(acc_y*acc_y)+(acc_z*acc_z));  //Calculate the total accelerometer vector
  //57.296 = 1 / (3.142 / 180) The Arduino asin function is in radians
  angle_pitch_acc = asin((float)acc_y/acc_total_vector)* 57.296;       //Calculate the pitch angle
  angle_roll_acc = asin((float)acc_x/acc_total_vector)* -57.296;       
  
  angle_pitch_acc -= 0.0;                                              //Accelerometer calibration value for pitch
  angle_roll_acc -= 0.0;                                              

  if(set_gyro_angles){                                                 //If the IMU is already started
    angle_pitch = angle_pitch * 0.9996 + angle_pitch_acc * 0.0004;     //Correct the drift of the gyro pitch angle with the accelerometer pitch angle
    angle_roll = angle_roll * 0.9996 + angle_roll_acc * 0.0004;        //Correct the drift of the gyro roll angle with the accelerometer roll angle
  }
  else{                                                                //At first start
    angle_pitch = angle_pitch_acc;                                     //Set the gyro pitch angle equal to the accelerometer pitch angle 
    angle_roll = angle_roll_acc;                                       
    set_gyro_angles = true;                                            //Set the IMU started flag
  }
  
  //To dampen the pitch and roll angles a complementary filter is used
  angle_pitch_output = angle_pitch_output * 0.9 + angle_pitch * 0.1;   //Take 90% of the output pitch value and add 10% of the raw pitch value
  angle_roll_output = angle_roll_output * 0.9 + angle_roll * 0.1;      //Take 90% of the output roll value and add 10% of the raw roll value
  

 while(micros() - loop_timer < 4000);                                 //Wait until the loop_timer reaches 4000us (250Hz) before starting the next loop
 loop_timer = micros();//Reset the loop timer

// Calibrate during the first five seconds
  while (millis() < 5000) {            
    TL = analogRead(sensorPinTL);
    BL = analogRead(sensorPinBL);
    TR = analogRead(sensorPinTR);
    BR = analogRead(sensorPinBR);
    
// Record the maximum sensor value
    if (TL > sensorMaxTL) {sensorMaxTL = TL;}
    if (BL > sensorMaxBL) {sensorMaxBL = BL;}
    if (TR > sensorMaxTR) {sensorMaxTR = TR;}
    if (BR > sensorMaxBR) {sensorMaxBR = BR;}
    
    if (TL < sensorMinTR) {sensorMinTR = TL;}
    if (BL < sensorMinTR) {sensorMinTR = BL;}
    if (TR < sensorMinTR) {sensorMinTR = TR;}
    if (BR < sensorMinTR) {sensorMinTR = BR;}
} 
// Signal the end of the calibration period

// Read the sensor
  TL = analogRead(sensorPinTL); // Top left sensor
  BL = analogRead(sensorPinBL); // Bottom left sensor
  TR = analogRead(sensorPinTR); // Top right sensor
  BR = analogRead(sensorPinBR); // Bottom right sensor

// Apply the calibration to the sensor reading
  TL = map(TL, sensorMinTL, sensorMaxTL, 0, 510);
  BL = map(BL, sensorMinBL, sensorMaxBL, 0, 510);
  TR = map(TR, sensorMinTR, sensorMaxTR, 0, 510);
  BR = map(BR, sensorMinBR, sensorMaxBR, 0, 510);
  
// In case the sensor value is outside the range seen during calibration
  TL = constrain(TL, 0, 510);
  BL = constrain(BL, 0, 510);
  TR = constrain(TR, 0, 510);
  BR = constrain(BR, 0, 510);

  int DT = 10000; //Delay between sending values
  int TE = 5; //Tolerance between differences in horizontal and vertical sensors (stops the motors)

Rest of the remaining code.... since I exceeded 9000 character limit in message:

//Sends analog values in this format: i.e. <380,148,224,260,5000,79,20.50>
  Serial.print("<");
  Serial.print(TL);
  Serial.print(","); 
  Serial.print(BL);
  Serial.print(","); 
  Serial.print(TR);
  Serial.print(",");
  Serial.print(BR);
  Serial.print(",");
  Serial.print(DT);
  Serial.print(",");
  Serial.print(TE);
  Serial.print(",");
  Serial.print(angle_roll_output);
  Serial.print(">");
  
  Serial.println();   

  HC12.print("<"); 
  HC12.print(TL);
  HC12.print(",");  
  HC12.print(BL);
  HC12.print(",");
  HC12.print(TR);
  HC12.print(",");
  HC12.print(BR);
  HC12.print(",");
  HC12.print(DT);
  HC12.print(",");
  HC12.print(TE);
  HC12.print(",");
  HC12.print(angle_roll_output);
  HC12.print(">");
  
  HC12.println();

  delay(DT);             
}

void setup_mpu_6050_registers(){
  //Activate the MPU-6050
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
  Wire.write(0x6B);                                                    //Send the requested starting register
  Wire.write(0x00);                                                    //Set the requested starting register
  Wire.endTransmission();                                             
  //Configure the accelerometer (+/-8g)
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
  Wire.write(0x1C);                                                    //Send the requested starting register
  Wire.write(0x10);                                                    //Set the requested starting register
  Wire.endTransmission();                                             
  //Configure the gyro (500dps full scale)
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
  Wire.write(0x1B);                                                    //Send the requested starting register
  Wire.write(0x08);                                                    //Set the requested starting register
  Wire.endTransmission();                                             
}

void read_mpu_6050_data(){                                             //Subroutine for reading the raw gyro and accelerometer data
  Wire.beginTransmission(0x68);                                        //Start communicating with the MPU-6050
  Wire.write(0x3B);                                                    //Send the requested starting register
  Wire.endTransmission();                                              //End the transmission
  Wire.requestFrom(0x68,14);                                           //Request 14 bytes from the MPU-6050
  while(Wire.available() < 14);                                        //Wait until all the bytes are received
  acc_x = Wire.read()<<8|Wire.read();                                  
  acc_y = Wire.read()<<8|Wire.read();                                  
  acc_z = Wire.read()<<8|Wire.read();                                  
  temp = Wire.read()<<8|Wire.read();                                   
  gyro_x = Wire.read()<<8|Wire.read();                                 
  gyro_y = Wire.read()<<8|Wire.read();                                 
  gyro_z = Wire.read()<<8|Wire.read();                                 
}

If your program is too long then post the .INO file as an attachment. That way there won't be any errors from joining bits together.

What Arduino are you using?

Why would anyone need a gyro for a solar tracker - don't you just aim where the light is brightest?

...R

Hi I'm using arduino pro mini 3.3 volt version
The mpu6050 is being implemented after my structure broke from over rotating. This happens because of two reasons either because my HC 12 transmitters loose connection due to grounding plane issues and my code keeps telling the motors to spin and they don't stop or because my tolerance is too low and the tracker keeps on telling the motors to move that's why I want to place the mpu6050 sensor so that I can place angle limits for my elevation motor travel. I've attached the Ino file

DUAL_AXIS_SOLAR_TRACKING_BTS7960_TRANSMIT_R2.ino (10.3 KB)

Let's start with the simple stuff. What is the HC05 supposed to do - where does it get data from and what is the data?

My strong suspicion is that if you implement the HC05 stuff correctly there will be no need for the the Gyro. Adding complexity is not a good strategy.

Don't expect SoftwareSerial to work above 38400 baud and 9600 would be more sensible.

...R

The HC-12 module transmits information wirelessly between transmitter and receiver (another arduino mini with two h-bridges to drive motors).

I am transmitting 4 photoresistor values, a tolerance value, a delay time,
and the angle was supposed to be the sixth value.

In retrospect, the tolerance value and delay time don't need to be transferred.
I just have to figure out how to put them in the receiver code.

I am using your tutorial/guide/code for parsing serial data from what I remember.

I was transferring data successfully when I made a dipole antenna on the transmitter side.
Some times what happens is if the connection is lost, and the code on the receiver side tells the motors to spin it won't stop because it stops receiving updated photoresistor analog values.

The whole purpose of me using the HC-12 was adding value to the project:

  1. Before wires were connected from transmitter to the receiver and they would get caught while rotating along azimuth, plus I didn't have to deal with routing them properly.

  2. Easier to not use long wires between transmitter and receiver for larger solar projects.

So currently I have a total of seven values (six of them as integer values, the seventh as a float?) being transmitted in this format:

<380,148,224,260,5000,79,float angle number>

I am using the MPU6050 as an angle limit switch

Wouldn't it have been a whole lot easier to install real limit switches?

Pete

How often is the message sent?

It is a good idea to send the message at regular intervals (perhaps a few times per second) even if the data does not change. If the Rx does not get a message within the expected time it should shut off the motor.

In this case it would also seem wise to have limit switches that would prevent excessive motion.

...R

I'm making the design modular, so if I make it bigger, I want to minimize wiring, additional parts, assembly time as much as possible. Hence the reason for the angle sensor hooked up to breadboard on transmitter side.

I'm transmitting every 10 seconds.

I found this code here:

It's simpler.
It works on its own fine.

//Written by Ahmet Burkay KIRNIK
//TR_CapaFenLisesi
//Measure Angle with a MPU-6050(GY-521)

#include<Wire.h>

const int MPU_addr=0x68;
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;

int minVal=265;
int maxVal=402;

double x;
double y;
double z;
 
void setup(){
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);
  Wire.write(0);
  Wire.endTransmission(true);
  Serial.begin(9600);
}
void loop(){
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr,14,true);
  AcX=Wire.read()<<8|Wire.read();
  AcY=Wire.read()<<8|Wire.read();
  AcZ=Wire.read()<<8|Wire.read();
  
    int xAng = map(AcX,minVal,maxVal,90,-90);
    int yAng = map(AcY,minVal,maxVal,90,-90);
    int zAng = map(AcZ,minVal,maxVal,90,-90);

       x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);
       y= RAD_TO_DEG * (atan2(-xAng, -zAng)+PI);
       z= RAD_TO_DEG * (atan2(-yAng, -xAng)+PI);

   //  Serial.print("AngleX= ");
   //  Serial.println(x);

     Serial.print("AngleY= ");
     Serial.println(y);

   //  Serial.print("AngleZ= ");
   //  Serial.println(z);
     Serial.println("-----------------------------------------");
     delay(400);
}

After integrating it into the transmit code it works fine.
Just have to fine tune the mapping and offset values.
Want to make the horizontal zero and make the 90 degrees 90 instead of 270.

//Special thanks to geobruce at instructables.com
//Special thanks to Robin2 and his code for parsing data, and others on arduino forums (serial input basics guide by Robin2 was really useful) as well as my CS friends.
//HC-12 transmitter code for dual axis solar tracking.

//Written by Ahmet Burkay KIRNIK
//TR_CapaFenLisesi
//Measure Angle with a MPU-6050(GY-521)

#include<Wire.h>

const int MPU_addr=0x68;
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;

int minVal=265;
int maxVal=402;

double x;
double y;
double z;

#include <SoftwareSerial.h>
SoftwareSerial HC12(11,10); // (HC-12 TX Pin, HC-12 RX)

const int sensorPinTL = A0;  
const int sensorPinBL = A1;
const int sensorPinTR = A2;  
const int sensorPinBR = A3;  

// The sensor value
int TL = 0; 
int BL = 0;
int TR = 0;         
int BR = 0;

// Minimum sensor value, more light is seen
int sensorMinTL = 0; 
int sensorMinBL = 0;
int sensorMinTR = 0;        
int sensorMinBR = 0;

int sensorMaxTL = 1023; 
int sensorMaxBL = 1023; 
int sensorMaxTR = 1023;           
int sensorMaxBR = 1023; 

void setup() {
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);
  Wire.write(0);
  Wire.endTransmission(true);
  
  Serial.begin(9600);
  HC12.begin(9600); //serial port to HC12
}

void loop() {
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr,14,true);
  
  AcX=Wire.read()<<8|Wire.read();
  AcY=Wire.read()<<8|Wire.read();
  AcZ=Wire.read()<<8|Wire.read();
  
  int xAng = map(AcX,minVal,maxVal,-90,90);
  int yAng = map(AcY,minVal,maxVal,-90,90);
  int zAng = map(AcZ,minVal,maxVal,-90,90);

  x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);
  y= RAD_TO_DEG * (atan2(-xAng, -zAng)+PI);
  z= RAD_TO_DEG * (atan2(-yAng, -xAng)+PI);

// Calibrate during the first five seconds
  while (millis() < 5000) {            
    TL = analogRead(sensorPinTL);
    BL = analogRead(sensorPinBL);
    TR = analogRead(sensorPinTR);
    BR = analogRead(sensorPinBR);
    
// Record the maximum sensor value
    if (TL > sensorMaxTL) {sensorMaxTL = TL;}
    if (BL > sensorMaxBL) {sensorMaxBL = BL;}
    if (TR > sensorMaxTR) {sensorMaxTR = TR;}
    if (BR > sensorMaxBR) {sensorMaxBR = BR;}
    
    if (TL < sensorMinTR) {sensorMinTR = TL;}
    if (BL < sensorMinTR) {sensorMinTR = BL;}
    if (TR < sensorMinTR) {sensorMinTR = TR;}
    if (BR < sensorMinTR) {sensorMinTR = BR;}
} 
// Signal the end of the calibration period

// Read the sensor
  TL = analogRead(sensorPinTL); // Top left sensor
  BL = analogRead(sensorPinBL); // Bottom left sensor
  TR = analogRead(sensorPinTR); // Top right sensor
  BR = analogRead(sensorPinBR); // Bottom right sensor

// Apply the calibration to the sensor reading
  TL = map(TL, sensorMinTL, sensorMaxTL, 0, 510);
  BL = map(BL, sensorMinBL, sensorMaxBL, 0, 510);
  TR = map(TR, sensorMinTR, sensorMaxTR, 0, 510);
  BR = map(BR, sensorMinBR, sensorMaxBR, 0, 510);
  
// In case the sensor value is outside the range seen during calibration
  TL = constrain(TL, 0, 510);
  BL = constrain(BL, 0, 510);
  TR = constrain(TR, 0, 510);
  BR = constrain(BR, 0, 510);

  int DT = 1000; //Delay between sending values
  int TE = 5; //Tolerance between differences in horizontal and vertical sensors (stops the motors)

//Sends analog values in this format: i.e. <380,148,224,260,5000,79, 45.5>
  Serial.print("<");
  Serial.print(TL);
  Serial.print(","); 
  Serial.print(BL);
  Serial.print(","); 
  Serial.print(TR);
  Serial.print(",");
  Serial.print(BR);
  Serial.print(",");
  Serial.print(DT);
  Serial.print(",");
  Serial.print(TE);
  Serial.print(",");
  Serial.print(y);
  Serial.print(">");
  
  Serial.println();   

  HC12.print("<"); 
  HC12.print(TL);
  HC12.print(",");  
  HC12.print(BL);
  HC12.print(",");
  HC12.print(TR);
  HC12.print(",");
  HC12.print(BR);
  HC12.print(",");
  HC12.print(DT);
  HC12.print(",");
  HC12.print(TE);
  HC12.print(",");
  HC12.print(y);
  HC12.print(">");
  
  HC12.println();

  delay(DT);             
}