Here goes the basic code and details for the Arduino CAT controlled or Yaesu "emulator" for remote controlling a VFO from a PC.
I tested against "Rigresident" and "Commander v5.8.7" software using 9K6 on the serial port (Arduino USB serial console) and booth Yaesu 857 and 817 command set (are the same for all that matters).
The control of the VFO chip itself (Si570, AD9850 etc) is not implemented on the code, there are comments were it should be placed. Consider the code as a base for your own solution.
If copy past of the following code does not work for you because of blogger formatting let me know, I can send code on email.
// Code starts here
//
// Basic code for remote control of an VFO base on the Arduino platform using CAT software or Hamlib
//
// Emulates basic functions of an FT857 (and similar Yaesu) in the Arduino platform from the perspective of the CAT software
// set mode, set frequence and get frequency only at the moment
//
// By: CT2GQV - Ricardo
//
// Licence: GPL - use according, in no way I will be responsable for the magic smoke you may get!
//
// Information sources: Hamlib, FT857.h from VE3BUX
//
// to be done: add s-meter reading and sending. Add code to control Si5351, Si570, ad9850/1 etc
// any help is apreciated
#include
#include
#include
// whatever lcd is used, might need some changes
// LCD control, SDA and SCL to analog 4 and 5 pin
#define I2C_ADDR 0x27 // I2C Address for my LCD, found with I2C scanner
#define BACKLIGHT_PIN 3
#define En_pin 2
#define Rw_pin 1
#define Rs_pin 0
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7
LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);
// modes as going/coming from rig control, no need for hex since it will the last byte in the array, diferent story if it was the first....
#define LSB 0
#define USB 1
#define CW 2
#define AM 4
#define FM 8
#define RTTY 10
#define PKT 12
// this could be done in a diferent way... see comments on the code about "to_bcd_be"
// ...don't remember coding so bad in the past years... oh well, get's the job done
#define HZERO 0x00
#define HONE 0x01
#define HTWO 0x02
#define HTHRE 0x03
#define HFOUR 0x04
#define HFIVE 0x05
#define HSIX 0x06
#define HSEVEN 0x07
#define HEIGHT 0x08
#define HNINE 0x09
#define HTEN 0x10
#define HTWENTY 0x20
#define HTHIRTY 0x30
#define HFOURTY 0x40
#define HFIFTY 0x50
#define HSIXTY 0x60
#define HSEVENTY 0x70
#define HEIGHTY 0x80
#define HNINETY 0x90
int incomingByte; // for incoming serial data from rig control soft.
int counter_byte = 1; // just a counter for the bytes in radiocommand array
int radiocommand[5]; // array to keep the previous commands from the rig control software...
int i; // just an aux counter
char a[8]; // will keep the hex to send to rig software when requests frequency vfo is in
// in the future get the next values (start up frequency and mode) from saved configuration...
// 4 4 3,7 5 0.5 1 0 (this would be 443Mhz 750Khz and 513 Hz (show up as 443,750.51)
// 8 5 0 5 1 3 ( 850 Khz and 512 Hz (show up as 850.51)
int myfrequency[]={1,4,4,7,5,0,1,2,5}; // to rig control only first 8 values are sent...for vfo connected that a diferent story
int mymode = USB; // mode usb,lsb,cw,am,fm,rtty,pkt
// setup function of the Arduino
void setup() {
Serial.begin(9600); // 9k6 speed, can be reduced.
lcd.begin (20,4,LCD_5x8DOTS); lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE); lcd.setBacklight(HIGH); // 20x4 lines display LCD
lcd.home(); lcd.print(" CAT controlled "); // just dummy info, trying just to keep for 16 case lcd changes to 16x2
lcd.setCursor(0,1);
switch (mymode) {case 0: lcd.print("LSB "); break; case 1: lcd.print("USB "); break; case 2: lcd.print("CW "); break; case 4: lcd.print("AM "); break;
case 8: lcd.print("FM "); break; case 10: lcd.print("RTTY "); break; case 12: lcd.print("PKT "); break; }
for (i = 0; i < 8; i = i + 1) { if (i==3 || i==6) {lcd.print(".");}; lcd.print(myfrequency[i]); } // print the startup frequency
////////////////////////////////////////
// put code here to initialize vfo connected to Arduino
///////////////////////////////////////
}
void loop() {
////////////// RIG CONTROL PART ////////////////////////////////////////////////
// do we have serial data?...
if (Serial.available() > 0) {
incomingByte = Serial.read(); // read the incoming byte command from the serial line
radiocommand[counter_byte]=incomingByte; // place the incoming byte on the array
////// let's start switching the commands sent from rig control software...
// if the rig control software comand is 0x03 then send out current frquency by request of rig control software
if (incomingByte==3 && radiocommand[4]==0 && radiocommand[3]==0 && radiocommand[2]==0 && radiocommand[1]==0 ) {
// loop in myfrequency starting on the first vaule we have for frequency until the maximum of the myfrequency array (8)
// if anyone has time to change the following this would be much better job with "to_bcd_be" from hamlib, basical convert to nibles and join and send...
for (i = 0; i < 8; i = i + 2 ) { //loop all digits from 0 to 7 from the myfrequency array, join two by two and send the HEX value
switch (myfrequency[i]) {
case 0: a[i]= HZERO; break; case 1: a[i]= HTEN; break; case 2: a[i]= HTWENTY; break; case 3: a[i]= HTHIRTY; break;
case 4: a[i]= HFOURTY; break; case 5: a[i]= HFIFTY; break; case 6: a[i]= HSIXTY; break; case 7: a[i]= HSEVENTY; break;
case 8: a[i]= HEIGHTY; break; case 9: a[i]= HNINETY; break; } // end switch first digit
switch (myfrequency[i+1]) {
case 0: a[i+1]= HZERO; break; case 1: a[i+1]= HONE; break; case 2: a[i+1]= HTWO; break; case 3: a[i+1]= HTHRE; break;
case 4: a[i+1]= HFOUR; break; case 5: a[i+1]= HFIVE; break; case 6: a[i+1]= HSIX; break; case 7: a[i+1]= HSEVEN; break;
case 8: a[i+1]= HEIGHT; break; case 9: a[i+1]= HNINE; break; } // end switch of the second digit
} // end of the for loop to read frequency we are in and and convert to BCD
// lets now send the frequency data to rig control software in this format a1a2.b1b2.c1c2.d1d2.ee (ee is mode)
Serial.write(a[0]+a[1]); Serial.write(a[2]+a[3]); Serial.write(a[4]+a[5]); Serial.write(a[6]+a[7]); Serial.write(mymode);
//////////////////////
// no code is needed here because we are just sending the present frequency we are in
/////////////////////////////////////////////
} // end send out current frequency
// if the rig control software command is 0x01 then set frequency whith the values sent aa.bb.cc.dd.0x01
if (radiocommand[5]==1) {
int tempo;
tempo = radiocommand[1]>>4; myfrequency[0]=tempo; tempo = radiocommand[1]&0x0f; myfrequency[1]=tempo;
tempo = radiocommand[2]>>4; myfrequency[2]=tempo; tempo = radiocommand[2]&0x0f; myfrequency[3]=tempo;
tempo = radiocommand[3]>>4; myfrequency[4]=tempo; tempo = radiocommand[3]&0x0f; myfrequency[5]=tempo;
tempo = radiocommand[4]>>4; myfrequency[6]=tempo; tempo = radiocommand[4]&0x0f; myfrequency[7]=tempo;
// print the new frequency we were requested to go to by rig control software
lcd.setCursor(0,1);
switch (mymode) {case 0: lcd.print("LSB "); break; case 1: lcd.print("USB "); break; case 2: lcd.print("CW "); break; case 4: lcd.print("AM "); break;
case 8: lcd.print("FM "); break; case 10: lcd.print("RTTY "); break; case 12: lcd.print("PKT "); break; }
for (i = 0; i < 8; i = i + 1) { if (i==3 || i==6) {lcd.print(".");}; lcd.print(myfrequency[i]); }
//////////////////////////////////
// put code here to set the new frequency on the vfo... ex: set_vfo(myfrequeny);
//////////////////////////////////
} // end of rig control command to set a new frequency on the VFO
// set mode command sent from rig control software
if (incomingByte==7 && radiocommand[4]==0 && radiocommand[3]==0 && radiocommand[2]==0) { //rig control will set mode on the arduino
if (radiocommand[1]==0){ mymode=LSB; }; if (radiocommand[1]==1){ mymode=USB;};
if (radiocommand[1]==2){ mymode=CW;}; if (radiocommand[1]==8){ mymode=FM;};
if (radiocommand[1]==4){ mymode=AM;}; if (radiocommand[1]==10){ mymode=RTTY;};
if (radiocommand[1]==12){ mymode=PKT; };
// will print mode on the lcd after mode change requested by rig control software..and also the frequency just to refresh the screen
lcd.setCursor(0,1);
switch (mymode) {case 0: lcd.print("LSB "); break; case 1: lcd.print("USB "); break; case 2: lcd.print("CW "); break; case 4: lcd.print("AM "); break;
case 8: lcd.print("FM "); break; case 10: lcd.print("RTTY "); break; case 12: lcd.print("PKT "); break; }
for (i = 0; i < 8; i = i + 1) { if (i==3 || i==6) {lcd.print(".");}; lcd.print(myfrequency[i]); } // print the startup frequency
//////////////////////////////////
// put code here to change mode ex; set_mode(mymode)
// if mymode = 1 (USB) then switch on digital pin 1...
// if mymode = 2 (CW) then switch on digital pin 2...
//////////////////////////////////
} // end of set mode by rig control
///// end of pattern/command recognition part
counter_byte++; // increment the position on the array read from the serial line
if (counter_byte>5) {counter_byte=1; }; // if we reached the end of the array.. that is previous counter byte = 5 and now 6 because we incremented before
} // end of if serial avaiable cycle and command execution from RIG control software
///////////////// END / RIG CONTROL PART //////////////////////////////////////////////////
// put code on the next lines to read button/rotary press to change frequency, change mode etc..
// and other stuff....
/////////////////
} // end of main Arduino loop
// end of code
The LCD I used is this one (20x4 I2C connection):
I changed the code to use only 2 lines of the LCD since a 16x2 is more common than a 20x4.
LCD connection as follow:
GND from LCD to Arduino Pin Gnd (on power bus)
VCC from LCD to Arduino Pin 5v (on power bus)
SDA from LCD to Arduino Pin Analog A4 (on analog bus)
SCL from LCD to Arduino Pin Analog A5 (on analog bus)
You can use a different LCD, just change the code.
Have a nice weekend!
No comments:
Post a Comment