Hardware components | ||||||
| × | 1 |
With a requirement to use only one coax feeder cable into a radio shack for half a dozen aerials I needed a means of remotely switching RF relays. This could be done with just a multiway cable and switch, however it would be much more elegant with an LCD display to show the antenna selected with a BCD output to control a remote switch with an autosave of the selected antenna on power off and restore on power on.
The project is based around and Arduino Nano using digital ports D2 and D3 for up/down selector momentary toggle switch type (on)off(on). A two line x 16 I2C LCD interface on SCL/SDA ports and outputs on analogue ports A0, A1 and A2 to drive line voltage level converters / output buffers.
Aerial Switch Controller Software
C/C++Code is designed to toggle up and down between pages of text on LCD screen, and generate a 3bit BCD output for the page selected and store the selected page to EEPROM. Thus after power down, on the next reboot the system will restart with the last setting. Using port connections to an Arduino NANO as per the schematic this code can be used to drive a remote BCD decoder for selecting remote RF relays. LCD displays antenna selected with 16 characters available for description. First line of display can be used for station callsign and Maidenhead locator. System settings are only saved to eeprom when changing the antenna selection thus write cycles are kept to a minimum and not for each program loop. A test for eeprom value is included at the end of the program loop to ensure the returned value is within the scope of this program.
//Antenna switch control software Issue-1
//description, antenna relay switch controller with LCD display display using 3 wire [binary] control to switch up to 6 remote RF relays. Requires ATmega328P-PU (Arduino Nano), 1x SPDT toggle switch [mom-off-mom] and either I2C 16x2 or 20x4 LCD module
//display information and relay switch driver(s) are stored in EEPROM and recalled on power rebootA
//Added test for EEPROM corruption, code lines 203 204..
//David Allen G8LHD © 22nd June 2021
#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h> //library installation required from GitHub
// * Download LiquidCrystal_I2C zipped library from GitHub https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library
// * install in Arduino > libraries > new folder "LiquidCrystal_I2C"
// * After placing in folder run Arduino IDE software, Sketch > Include Library > Add.ZIP Library...
// * May be necessary to reboot Arduino IDE software after library installation
// * Change text strings in following lines of code to your own preferences
// * Line56, declare lcd type, 16 x 2 line default or 20 character x 4 line alternative.
// * Line80, add station call sign
// * Line131; add antenna description, NOTE fill LCD text string statement with spaces to stop LCD overlap of text string.
// * Line142; add antenna description
// * Line152; add antenna description
// * Line162; add antenna description
// * Line172; add antenna description
// * Line182; add antenna description
// * code lines 91 "if(page_counter <7)" and code line 110 "page_counter= 7;" the number used reflects the highest page number if not using all antenna ports, binary address '110' is used on last page, all relays off.
//-------Pins-----//
int up = 2; //Up button, digital pin2, PD2 ATmega328P 28pin dip = pin4, normally open = LOW, closed = HIGH
int down = 3; //Down button, digital pin3, PD3 ATmega328P 28pin dip = pin5, normally open = LOW, closed = HIGH
int outputA0 = 14; //A0, digital pin14, ATmega328P 28pin dip = pin23
int outputA1 = 15; //A1, digital pin15, ATmega328P 28pin dip = pin24
int outputA2 = 16; //A2, digital pin16, ATmega328P 28pin dip = pin25
//----variable to move between pages----//
int page_counter;
//---------Storage debounce function-----//
bool current_up = LOW;
bool last_up=LOW;
bool last_down = LOW;
bool current_down = LOW;
void setup() {
checkpagecounterState(); //----Check last EEPROM stored page count----//
pinMode(up,INPUT); //initialize digital pin PD2 as an input.
pinMode(down,INPUT); //initialize digital pin PD3 as an input.
pinMode(outputA0,OUTPUT); //initialize analogue pin A0 as an output.
pinMode(outputA1,OUTPUT); //initialize analogue pin A1 as an output.
pinMode(outputA2,OUTPUT); //initialize analogue pin A2 as an output.
//----Check 0x27 is correct I2C address for LCD display----//
LiquidCrystal_I2C lcd(0x27, 16, 2); // LiquidCrystal_I2C lcd(0x27, 20, 4); // use with 4 line LCD display
lcd.init(); // Initialize the LCD
lcd.backlight(); // turn on backlight
lcd.clear(); // clear display
}
//----De-bouncing function for all buttons----//
boolean debounce(boolean last, int pin)
{
boolean current = digitalRead(pin);
if (last != current)
{
delay(40); //----40ms delay for debounce----//
current = digitalRead(pin);
}
return current;
}
void loop() {
LiquidCrystal_I2C lcd(0x27, 20, 4); //this is required inside loop for lcd.functions to work
lcd.backlight();
lcd.setCursor(0,0); //----indent one charachter, line 0----//
lcd.print("Gxxxx Loc xxxxxx"); //write station callsign and Maidenhead grid square locator on first line of LCD display
// lcd.print("1234567812345678"); Character number guide for 16 x 2 LCD display
current_up = debounce(last_up, up); //Debounce for Up button
current_down = debounce(last_down, down); //Debounce for Down button
//----Page counter function to move between pages----//
//----change code lines 91 "if(page_counter <7)" and code line 110 "page_counter= 7;" replace 7 with highest number of pages----//
//Page Up
if (last_up== LOW && current_up == HIGH){
lcd.clear(); //When page is changed, lcd clear to print new page
if(page_counter <7){ //Page counter never higher than 7(total of pages)
page_counter= page_counter +1; //Page up
}
else{
page_counter= 1; //return to page 1
}
}
last_up = current_up;
//Page Down
if (last_down== LOW && current_down == HIGH){
lcd.clear(); //When page is changed, lcd clear to print new page
if(page_counter >1){ //Page counter never lower than 1 (total of pages)
page_counter= page_counter -1; //Page down
}
else{
page_counter= 7; //----return to page 7----//
}
}
last_down = current_down;
EEPROM.update(0, page_counter); //----write to ATmega328 EEPROM adress 0, page_counter variable (1-7)----//
//----Aerial Switch function----//
switch (page_counter) {
case 1:{ //Design of home page 1
digitalWrite(outputA0,LOW); //----antenna port address 000, A0 least significant bit----//
digitalWrite(outputA1,LOW);
digitalWrite(outputA2,LOW);
lcd.setCursor(0,1);
lcd.print("A 6m/2m/70c Vert");
// lcd.print("1234567812345678"); Character number guide for 16 x 2 LCD display
}
break;
case 2: { //Design of page 2
digitalWrite(outputA0,HIGH); //----antenna port address 001, A0 least significant bit----//
digitalWrite(outputA1,LOW);
digitalWrite(outputA2,LOW);
lcd.setCursor(0,1); //indent one charachter, print on line 1
lcd.print("B 144MHz 2m Horz");
// lcd.print("1234567812345678");
}
break;
case 3: { //Design of page 3
digitalWrite(outputA0,LOW); //----antenna port address 010, A0 least significant bit----//
digitalWrite(outputA1,HIGH);
digitalWrite(outputA2,LOW);
lcd.setCursor(0,1);
lcd.print("C 50MHz 6m Horz ");
// lcd.print("1234567812345678");
}
break;
case 4: { //Design of page 4
digitalWrite(outputA0,HIGH); //----antenna port address 011, A0 least significant bit----//
digitalWrite(outputA1,HIGH);
digitalWrite(outputA2,LOW);
lcd.setCursor(0,1);
lcd.print(" ");
// lcd.print("1234567812345678");
}
break;
case 5: { //Design of page 5
digitalWrite(outputA0,LOW); //----antenna port address 100, A0 least significant bit----//
digitalWrite(outputA1,LOW);
digitalWrite(outputA2,HIGH);
lcd.setCursor(0,1);
lcd.print(" ");
// lcd.print("1234567812345678");
}
break;
case 6: { //Design of page 6
digitalWrite(outputA0,HIGH); //----antenna port address 101, A0 least significant bit----//
digitalWrite(outputA1,LOW);
digitalWrite(outputA2,HIGH);
lcd.setCursor(0,1);
lcd.print(" ");
// lcd.print("1234567812345678");
}
break;
case 7: { //Design of page 7
digitalWrite(outputA0,LOW); //----unused antenna port address 110, A0 least significant bit, all relays off.----//
digitalWrite(outputA1,HIGH);
digitalWrite(outputA2,HIGH);
lcd.setCursor(0,1);
lcd.print("All relays off ");
// lcd.print("1234567812345678");
}
break;
}//switch end
}//1st loop end
void checkpagecounterState() //----program loop for reading EEPROM adress 0 pagecounter last stored value----//
{
page_counter = EEPROM.read(0);
if (page_counter <1)return 1; //if eeprom value becomes corrupted returns a page_counter value of page 1
if (page_counter >7) return 1;
}//2nd loop end
//end
Comments