K5TRI Rotorduino Source Code

Update 4/8/2016: Code is now on GitHub https://github.com/michaelschulz/rotorduino

I finally found some time to post the source for my rotor controller I posted about a long time ago. Maybe some day I will also find time to make the schematic. I never drew schematics in a proper tool other than on a piece of paper. It should however be somewhat self explanatory. As the saying goes:”The documentation is in the source” :).


/*
Simple 3-wire rotor controller for tracking satellites.
This code uses an existing AZ only simple rotator to track satellites using the EASYCOM I
protocol.

This code was written by Michael Schulz (K5TRI) and is licensed under the GPLv2
Comments and improvements welcome at mschulz@creative-chaos.com

GPredict users:

In the antenna controller you need to set the Tolerance to 0.01. If left at
5.0 degrees, the value sent to the controller on switchover from 0 deg to 360 will go back
and forth causing the rotor to do two full turns!

*/

#include #include
#include "EEPROMAnything.h"
#include
//#include
//#include

// The shield uses the I2C SCL and SDA pins. On classic Arduinos
// this is Analog 4 and 5 so you can't use those for analogRead() anymore
// However, you can connect other I2C sensors to the I2C bus and share
// the I2C bus.

//Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

// These #defines make it easy to set the backlight color for use with Adafruit I2c LCD shield

/*#define RED 0x1
#define YELLOW 0x3
#define GREEN 0x2
#define TEAL 0x6
#define BLUE 0x4
#define VIOLET 0x5
#define WHITE 0x7
*/

struct azimuth_t
{
int az_cur;
} azim;

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(13, 12, 11,10, 6, 5);

unsigned char relayEXEpin = 9;
unsigned char relayROTpin = 8;
unsigned char rotButCCW = 3;
unsigned char rotButCW = 4;
char inputData[19];
int s;
int lastexe;
int idle;
int startidle;
int az_temp;
int b;
int predictInput[12];
byte startbyte;
int ButtonState = 0;
unsigned long time_on;
unsigned long time_off;
unsigned long time_diff;

int ButtonCW();
int ButtonCCW();

void setup()

{

// retrieve stored position from memory
// int az_cur;

EEPROM_readAnything(0, azim.az_cur);

// Make sure rotor is turned off
digitalWrite(relayEXEpin,LOW);

// set up the LCD's number of columns and rows:

lcd.begin(16, 2);
lcd.setCursor(0,0);
lcd.clear();

//display current postion of rotor

//Idle message while waiting for commands
lcd.clear();
lcd.print("K5TRI RotorDuino");
lcd.setCursor(0,1);
lcd.print("Current pos: ");
lcd.print(azim.az_cur);

// initialize the serial communications:

Serial.begin(9600);

// define relay pins for rotor control

pinMode(ledCCWpin,OUTPUT);
pinMode(ledCWpin,OUTPUT);
pinMode(relayEXEpin,OUTPUT);
pinMode(relayROTpin,OUTPUT);

pinMode(rotButCCW,INPUT);
pinMode(rotButCW,INPUT);

}

void loop()

{

startidle = (millis() /1000);

EEPROM_readAnything(0, azim.az_cur); // Get current position stored in EEPROM
azim.az_cur = constrain(azim.az_cur, 0, 360); //Limit rotor positioning between 0 and 360 degrees

//manual CCW button pressed
if (digitalRead(rotButCCW) == HIGH)
{
lcd.clear();
time_on = millis();
ButtonCCW();
//EEPROM_readAnything(0, azim.az_cur);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Current position: ");
lcd.setCursor(0,1);
lcd.print("Azimuth: ");
lcd.print(azim.az_cur);
lcd.print(" deg");
}

//manual CW button pressed

if (digitalRead(rotButCW) == HIGH)
{
lcd.clear();
time_on = millis();
ButtonCW();
//EEPROM_readAnything(0, azim.az_cur);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Current position: ");
lcd.setCursor(0,1);
lcd.print("Azimuth: ");
lcd.print(azim.az_cur);
lcd.print(" deg");
}

//turn off rotor
digitalWrite(relayEXEpin, LOW);

// wait for serial input full serial line data (min 12 bytes in buffer)

if (Serial.available() > 12) {

//read the first byte
startbyte = Serial.read();

// check for the start of the serial string (65) ASCII (A)
if (startbyte == 65)

{

for (s=0; s<12;s++)
{
predictInput[s] = Serial.read();

}

char az[5] = { predictInput[1], predictInput[2], predictInput[3] };

// write input value to serial for debugging
Serial.print("Input: ");
Serial.println(az);

int az_new = atoi(az); //Convert azimuth char string to integer

az_new = constrain(az_new, 0, 359); //limit azimuth between 0 and 359 degrees

// arite AZ value to serial for debugging purposes

Serial.print("AZ NEW: ");
Serial.println(az_new);

// Rotor function

// Calculate direction
long az_diff = az_new - azim.az_cur;

//If az_diff is < 0 then turn CCW
if (az_diff < 0) { digitalWrite(ledCCWpin,HIGH); digitalWrite(relayROTpin,LOW); } else digitalWrite(ledCCWpin,LOW); //If az_diff > 0 then turn CW
if (az_diff > 0) {
digitalWrite(ledCWpin,HIGH);
digitalWrite(relayROTpin,HIGH);
}

else digitalWrite(ledCWpin,LOW);

// Calculate timing

if (az_diff < 0) az_diff = -az_diff; unsigned long exec_time = az_diff * 180UL; //If az_diff > 5 degrees then turn. This can be set to whatever azimuth difference desired
if (az_diff > 5) {

// Turn rotor

lcd.clear();
lcd.setCursor(0,0);
lcd.print("Turning ...");

digitalWrite(relayEXEpin, HIGH);
delay(exec_time);
digitalWrite(relayEXEpin,LOW);

lcd.clear();
lcd.print("Current position:");
lcd.setCursor(0,1);
lcd.print(az_new);
lcd.print(" deg");

lastexe = (millis() / 1000);

//Set az_cur
azim.az_cur = az_new;
//Write az_cur to EEPROM
EEPROM_writeAnything(0,azim);

}

}
}

idle = startidle - lastexe;

if (idle > 59)

{
lcd.setCursor(0,0);
lcd.print("K5TRI RotorDuino");
lcd.setCursor(0,1);
lcd.print("Current pos: ");
lcd.print(azim.az_cur);
}
}

int ButtonCW()
{

while (digitalRead(rotButCW) == HIGH) {

lcd.setCursor(0,0);
lcd.print("Manual CW ");
lcd.setCursor(0,1);
EEPROM_readAnything(0,azim);

Serial.print("on: ");
Serial.println(time_on);
digitalWrite(ledCWpin,HIGH);
digitalWrite(relayROTpin,HIGH);
digitalWrite(relayEXEpin, HIGH);
time_off = millis();
Serial.print("off: ");
Serial.println(time_off);

time_diff=time_off-time_on;
Serial.print("diff: ");
Serial.println(time_diff);
b = (int) (time_diff / 180);
az_temp = azim.az_cur + b;
Serial.print("az_new: ");
Serial.println(az_temp);
lcd.print("Current pos: ");
lcd.print(az_temp);
lcd.print(" ");

lastexe = (millis() / 1000);

}

//Prevent current position to be greater than 360 when using manual
//button to turn CW

if (az_temp > 360) {(az_temp = 360);}
azim.az_cur = az_temp;
EEPROM_writeAnything(0,azim);

}

int ButtonCCW()

{

while (digitalRead(rotButCCW) == HIGH) {

lcd.setCursor(0,0);
lcd.print("Manual CCW ");
lcd.setCursor(0,1);
EEPROM_readAnything(0,azim);

Serial.print("on: ");
Serial.println(time_on);
digitalWrite(ledCCWpin,HIGH);
digitalWrite(relayROTpin,LOW);
digitalWrite(relayEXEpin, HIGH);
time_off = millis();
Serial.print("off: ");
Serial.println(time_off);

time_diff = time_off - time_on;
Serial.print("diff: ");
Serial.println(time_diff);
b = (int) (time_diff / 180);
az_temp = azim.az_cur - b;
Serial.print("az_new: ");
Serial.println(az_temp);
if (az_temp < 0) {(az_temp = 0);}
lcd.print("Current pos: ");
lcd.print(az_temp);
lcd.print(" ");

lastexe = (millis() / 1000);
}

// Prevent current position reading from being negative when using manual
// buttons to turn CCW

if (az_temp < 0) {(az_temp = 0);}
azim.az_cur = az_temp;
EEPROM_writeAnything(0,azim);

}

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s