I mess a lot with the Arduino, and along the way in this, I came across a module, DRA 818, which is found in resp. a VHF and UHF version, and which contains a full FM transciever, with an output of approx. 1W.
I chose the VHF version, which covers the range 134 to 174 MHz.
A little search on the internet gave me both a draft diagram, and various suggestions for what a program for the radio might look like.
This has led to this little case.
The schematics looks rather simple and claims only a few components.
The code can look like this:
/* DRA818V_VHF_DL3ED & OZ6YK
Nokia 5110 LCD Displays
Software with Nano Board
==============================================================================
by DL3ED 4.4.2015 & OZ6YK 10.03.2016
By first start, the Software has to be adjusted by use of the Setup button.
Remenber to use the rigthe pins.
==============================================================================
With the Setup button the following adjustmen can be made by use of the up, down buttons.
1.Volume 1-8
2.CTCSS 00,0Hz - 250,3Hz
3.Squelch 1-8
4.Tx Power Hi Low, 300mW oder 1Watt
5.Bandwide small or large, (12,5KHz or 25KHz)
6.Contras in the Display
7.Controle of the voltage
The values will be saved in the EEProm.
With the up , down button , the frequency of 134MHz to 144MHz in 25 KHz grid ,
from 144MHz to 146MHz in 12.5 KHz grid and set of 146MHz to 174MHz grid .
Long press on the button up , down , the rate of frequency
adjustment speeds .
Display
Rx 145,475 | Rx frequecy
Tx 145,475 | Tx frequecy
Pw. Low B.r | Power Low or Hi, bandwidth (sm or br)
SH.0 Sq.1 L.2 | Shift (0 or -), Squelch (0-8), Volume (0-8)
CTCSS 00,0 Hz | CTCSS Tones 0-250,3Hz
==============================================================================
!!!!!!!!!!!! Remember using the CTCSS set Squelch to 0 or it is not possible
!!!!!!!!!!!! to hear the othet station, unless they use CTCSS in there trans
!!!!!!!!!!!! mission as well.
Pins in the Display
org Display Arduino
1 = GND = GND
2 = LED = GND
3 = VCC = 3,3Volt
4 = CLK = Arduino 12
5 = DIN = Arduino 11
6 = DC = Arduino 10
7 = CE = Arduino 9
8 = RST = Arduino 8
Output Power Pin 7 Arduino
Taster Setup Pin 4 Arduino
Taster Down Pin 2 Arduino
Taster UP Pin 3 Arduino
Output Led Pin 13 Arduino
****************************************************************************************************/
#include <Adafruit_GFX.h>
#include <gfxfont.h>
#include <Adafruit_PCD8544.h>
#include <EEPROM.h>
Adafruit_PCD8544 display = Adafruit_PCD8544(12, 11, 10, 9, 8); //CLK, DIN, DC, CE, RST !!!!!!!!!!!!!!!!!!
//#define Tx 5
// #define Rx 6
char finalArray[4];
int time = 500;
int led_time = 1;
byte contrast = 60; // Contrast in Display
byte bw = 0; // Bandwith 0 for 12.5KHz or 1 for 25KHz
String bw_d = "Sm";
String bw_txt = "smal";
double ftx; // Tx Frequency in MHz 134.0000 - 174.0000
double ftxk;
double frx; // Rx Frequency in MHz 134.0000 - 174.0000
double frxk;
double volt; // Voltage
String sh = "0";
byte ctcss = 0;
String ctcss_t = "0000"; // ctcss frequency ( 0000 - 0038 );
//0000 = "no CTCSS"
String ctcss_r = "0000"; // ctcss frequency ( 0000 - 0038 );
//0000 = "no CTCSS"
String ctcssfre = "00.0";
int ctcss_test = 0;
byte squ = 0; // Squelch Level ( 0 - 8 ); 0 = "offen"
byte l = 2; // Volume 0-8
byte setup_power = 1; // 0-float , 0=500mW , float=1W must be inverted
String power = "LOW"; // da Transistor.
byte Pre_De = 0; // Pre/De on
byte Hojpas = 0; // Highpass on
byte Lavpas = 0; // Lowpass on
byte setupStatus = 0;
const int setuppower = 7; // To Power Hi/Low Output
const int setupPin = 4; // Pullup (a 4.7K resistor is necessary)
const int downPin = 3; // Downtaster Pullup
const int upPin = 2; // Uptaster Pullup
const int led = 13; // TestLED
byte addr = 0; // EEPROM Adress 1
byte addrf = 6 ;
//###########################################################
void setup()
{
Serial.begin(9600); // open serial at 9600 bps,
display.begin();
display.setContrast(contrast); //60 Contrast ########################
display.display();
display.clearDisplay(); // clears the screen and buffer
pinMode(setupPin, INPUT);
digitalWrite(setupPin, HIGH); // turn on pullup resistors
pinMode(setuppower, OUTPUT);
digitalWrite(setuppower, LOW);
pinMode(downPin, INPUT);
digitalWrite(downPin, HIGH); // turn on pullup resistors
pinMode(upPin, INPUT);
digitalWrite(upPin, HIGH); // turn on pullup resistors
pinMode(led, OUTPUT);
digitalWrite(led, LOW);
delay(1000);
//############################# Speicher Initialisieren #####################
if (digitalRead(setupPin) == HIGH) // Initializing the frequency , power , Squelch , scanning , etc.
{
// AT+DMOSETGROUP=Bandwith,Tx-Frequ.,Rx-Frequ.,TX-CTCSS,Squelch,Rx-CTCSS
// AT+DMOSETGROUP=1,145.4750,145.2750,0000,2,0000
frx = 1454750; // Rx frequency Startfrequency
ctcss = 0; // Tx/Rx CTCSS set to 0
squ = 0; // SquelchLevel
l = 1; // Volume
setup_power = 0; // Power 500mW
bw = 0;
frxk = frx / 1000;
contrast = 60;
addr = 0;
addrf = 6;
digitalWrite(setuppower, HIGH);
frequency_transfer();
EEPROM.write(addr,bw); // Bandwith
EEPROM.write(addr+1,squ); // Squelch
EEPROM.write(addr+2,setup_power); // SendePower
EEPROM.write(addr+3,ctcss); // CTCSS frequency
EEPROM.write(addr+4,l); // Volume
EEPROM.write(addr+5,contrast); // Contrast for Display
char* byteArray = reinterpret_cast<char*>(&frx);
for(int i=0;i<4;i++){EEPROM.write(addrf+i,byteArray[i]);}
display.clearDisplay(); // clears the screen and buffer
display.setTextSize(1);
display.setTextColor(BLACK);
display.setCursor(2,0); // Courser Horizontal, Vertikal in Pixel
display.print("Init");
display.setCursor(2,15); // Courser Horizontal, Vertikal in Pixel
display.print("Afsluttet");
display.setCursor(2,28);
display.print("Klar");
display.setCursor(2,40);
display.print("DL3ED & OZ6YK");
display.display();
delay(2000);
}
else {
bw = EEPROM.read(addr); // Bandwith
squ = EEPROM.read(addr+1); // Squelch
setup_power = EEPROM.read(addr+2); // SendePower
ctcss = EEPROM.read(addr+3); //CTCSS
l = EEPROM.read(addr+4); // Volume
contrast = EEPROM.read(addr+5);
for(int i=0;i<4;i++){delay(20);finalArray[i]=EEPROM.read(addrf+i);}
frx = *reinterpret_cast<double*>(finalArray);
}
ctcss_frequency_determine();
power_determine();
bw_determine();
frequency_choose();
frequency_transfer();
frequency_display();
}
//##############################################################
void loop()
{
led_time = led_time ++; // Test of sw !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if (led_time == 15000){
led_time = 0;
if (digitalRead(led) == LOW){digitalWrite(led,HIGH);}
else {digitalWrite(led,LOW);
}
}
if (digitalRead(downPin)==HIGH && digitalRead(upPin)==HIGH){time=500;}
if (digitalRead(downPin) == LOW){ // frequencye adjustment
if (frx <= 1740000 && frx > 1460000){frx = frx - 250;goto down_goto;}
//if (frx <= 1740000 && frx > 1340000){frx = frx - 125;goto down_goto;}
else {if (frx <= 1460000 && frx > 1440000){frx = frx - 125;}
else {if (frx <= 1440000 && frx >= 1340000){frx = frx - 250;}}
}
down_goto:
ctcss_frequency_determine();
power_determine();
frequency_choose();
frequency_transfer();
frequency_display();
if (time > 50){time = time - 50;}
delay(time);
}
if (digitalRead(upPin) == LOW){
if (frx >= 1340000 && frx < 1440000){frx = frx + 250;goto up_goto;}
//if (frx >= 1340000 && frx < 1740000){frx = frx + 100;goto up_goto;}
else {if (frx >= 1440000 && frx < 1460000){frx = frx + 125;}
else {if (frx >= 1460000 && frx <= 1740000){frx = frx + 250;}}
}
up_goto:
ctcss_frequency_determine();
power_determine();
frequency_choose();
frequency_transfer();
frequency_display();
if (time > 50){time = time - 50;}
delay(time);
}
if (digitalRead(setupPin) == LOW){
setup_transceiver();
frequency_transfer();
frequency_display();
}
}
//*************************** Underprogramme ***************************
void setup_transceiver(){
setup_volume();
setup_display_ctcss();
setup_squelch();
setup_power_Level();
setup_bandwith();
setup_contrast();
opvoltage();
delay(200);
}
//######################################################
void setup_contrast(){
do{ // loop Volume
if (digitalRead(downPin) == LOW){
if (contrast == 20);
else {contrast = contrast - 5 ;
display.setContrast(contrast);}
}
if (digitalRead(upPin) == LOW) {
if (contrast == 120);
else {contrast = contrast + 5 ;
display.setContrast(contrast);}
}
display.clearDisplay(); // clears the screen and buffer
display.setTextSize(1);
display.setTextColor(BLACK);
display.setCursor(0,0); // Courser Horizontal, Vertikal in Pixel
display.print("Contr.");
display.setCursor(0,24);
display.print(contrast);
display.display();
delay (300);
}
while (digitalRead(setupPin) == HIGH);
EEPROM.write(addr+5,contrast); // Volume store
delay(200);
}
//############################################
void opvoltage(){
do{
volt = analogRead(0); // AN0, Voltage
volt = volt / 100;
display.clearDisplay(); // clears the screen and buffer
display.setTextSize(1);
display.setTextColor(BLACK);
display.setTextSize(1.5);
display.setCursor(20,0);
display.print("Drifts-");
display.setCursor(20,10);
display.print("spaending");
display.setCursor(33,40);
display.print("Volt");
display.setTextSize(1.5);
display.setCursor(15,20);
display.print(volt,3);
display.display();
delay(200);
}
while (digitalRead(setupPin) == HIGH);
delay(200);
}
//######################################
void setup_bandwith(){
do{
if (digitalRead(downPin) == LOW){ // Key status
if (bw == 1);bw = 0;
bw_determine();
frequency_transfer();}
if (digitalRead(upPin) == LOW ){ // Key status
if (bw == 0);bw =1 ;
bw_determine();
frequency_transfer();}
display.clearDisplay(); // clears the screen and buffer
display.setTextSize(1.5);
display.setTextColor(BLACK);
display.setCursor(0,0); // Courser Horizontal, Vertikal in Pixel
display.print("Bandbr.");
display.setCursor(0,24);
display.print(bw_txt);
display.display();
delay(200);
}
while (digitalRead(setupPin) == HIGH);
EEPROM.write(addr,bw); // bandwith store
delay(200);
}
void bw_determine(){
if (bw == 0){bw_txt = "smal";bw_d = "Sm";}
else {bw = 1;bw_txt = "bred";bw_d = "Br";}
}
//#########################################
void setup_power_Level(){
do{
if (digitalRead(downPin) == LOW){ // Key status
if (setup_power == 1);
setup_power = 0;
power_determine();
frequency_transfer();}
if (digitalRead(upPin) == LOW){ // Key status
if (setup_power == 0);
setup_power = 1;
power_determine();
frequency_transfer();}
display.clearDisplay(); // clears the screen and buffer
display.setTextSize(1.5);
display.setTextColor(BLACK);
display.setCursor(0,0); // Courser Horizontal, Vertikal in Pixel
display.print("TxPower");
display.setCursor(0,24);
display.print(power);
display.display();
delay(200);
}
while (digitalRead(setupPin) == HIGH);
EEPROM.write(addr+2,setup_power); // SendePower store
}
void power_determine(){
if (setup_power == 0){digitalWrite(setuppower, HIGH); power = "Low";}
else {digitalWrite(setuppower, LOW); power = "Hi";}
}
//################################################
void setup_display_ctcss(){
do{ //loop loop_tx_ctcss
if (digitalRead(downPin) == LOW){
if (ctcss == 0);
else {ctcss = ctcss - 1 ;
ctcss_frequency_determine();
frequency_transfer();}
}
if (digitalRead(upPin) == LOW) {
if (ctcss == 38);
else {ctcss = ctcss + 1 ;
ctcss_frequency_determine();
frequency_transfer();}
}
display.clearDisplay(); // clears the screen and buffer
display.setTextSize(1.5);
display.setTextColor(BLACK);
display.setCursor(0,0); // Courser Horizontal, Vertikal in Pixel
display.print("CTCSS");
display.setCursor(0,24);
display.print(ctcssfre);
display.print("Hz");
display.display();
delay (300);
}
while (digitalRead(setupPin) == HIGH);
EEPROM.write(addr+3,ctcss); // CTCSS frequency store
delay(200);
}
void ctcss_frequency_determine()
{
if (ctcss == 0){ ctcssfre = "00,0";}
else if (ctcss == 1){ ctcssfre = "67,0";}
else if (ctcss == 2){ ctcssfre = "71,9";}
else if (ctcss == 3){ ctcssfre = "74,4";}
else if (ctcss == 4){ ctcssfre = "77,0";}
else if (ctcss == 5){ ctcssfre = "79,7";}
else if (ctcss == 6){ ctcssfre = "82,5";}
else if (ctcss == 7){ ctcssfre = "85,4";}
else if (ctcss == 8){ ctcssfre = "88,5";}
else if (ctcss == 9){ ctcssfre = "91,5";}
else if (ctcss == 10){ ctcssfre = "94,8";}
else if (ctcss == 11){ ctcssfre = "97,4";}
else if (ctcss == 12){ ctcssfre = "100,0";}
else if (ctcss == 13){ ctcssfre = "103,5";}
else if (ctcss == 14){ ctcssfre = "107,2";}
else if (ctcss == 15){ ctcssfre = "110,9";}
else if (ctcss == 16){ ctcssfre = "114,8";}
else if (ctcss == 17){ ctcssfre = "118,8";}
else if (ctcss == 18){ ctcssfre = "123,0";}
else if (ctcss == 19){ ctcssfre = "127,3";}
else if (ctcss == 20){ ctcssfre = "131,8";}
else if (ctcss == 21){ ctcssfre = "136,5";}
else if (ctcss == 22){ ctcssfre = "141,3";}
else if (ctcss == 23){ ctcssfre = "146,2";}
else if (ctcss == 24){ ctcssfre = "151,4";}
else if (ctcss == 25){ ctcssfre = "156,7";}
else if (ctcss == 26){ ctcssfre = "162,2";}
else if (ctcss == 27){ ctcssfre = "167,9";}
else if (ctcss == 28){ ctcssfre = "173,8";}
else if (ctcss == 29){ ctcssfre = "179,9";}
else if (ctcss == 30){ ctcssfre = "186,2";}
else if (ctcss == 31){ ctcssfre = "192,8";}
else if (ctcss == 32){ ctcssfre = "203,5";}
else if (ctcss == 33){ ctcssfre = "210,7";}
else if (ctcss == 34){ ctcssfre = "218,1";}
else if (ctcss == 35){ ctcssfre = "225,7";}
else if (ctcss == 36){ ctcssfre = "233,6";}
else if (ctcss == 37){ ctcssfre = "241,8";}
else if (ctcss == 38){ ctcssfre = "250,3";}
ctcss_t = String(ctcss,DEC);
if (ctcss <= 9){ctcss_t = ("000" + ctcss_t);}
else {ctcss_t = ("00" + ctcss_t);}
}
//####################################################
void setup_volume(){
do{ // loop Volume
if (digitalRead(downPin) == LOW){
if (l == 0);
else {l = l - 1 ;
Serial.print("AT+DMOSETVOLUME=");
Serial.println(l);}
}
if (digitalRead(upPin) == LOW) {
if (l == 8);
else {l = l + 1 ;
Serial.print("AT+DMOSETVOLUME=");
Serial.println(l);}
}
display.clearDisplay(); // clears the screen and buffer
display.setTextSize(1.5);
display.setTextColor(BLACK);
display.setCursor(0,0); // Courser Horizontal, Vertikal in Pixel
display.print("Lydst.");
display.setCursor(0,24);
display.print(l);
display.display();
delay (300);
}
while (digitalRead(setupPin) == HIGH);
EEPROM.write(addr+4,l); // Volume adjustment
delay(200);
}
//#######################################
void setup_squelch(){
do{ //loop Squelch
if (digitalRead(downPin) == LOW){
if (squ == 0);
else {squ = squ - 1 ;
frequency_transfer(); }
}
if (digitalRead(upPin) == LOW){
if (squ == 8);
else {squ = squ + 1 ;
frequency_transfer();}
}
display.clearDisplay(); // clears the screen and buffer
display.setTextSize(1.5);
display.setTextColor(BLACK);
display.setCursor(0,0); // Courser Horizontal, Vertikal in Pixel
display.print("Squelch");
display.setCursor(0,24);
display.print(squ);
display.display();
delay (300);
}
while (digitalRead(setupPin) == HIGH);
EEPROM.write(addr+1,squ); // Squelch store
delay(200);
}
//######################################################
void frequency_choose()
{
ftx = frx;
sh = "0";
if (frx >= 1456000 && frx <= 1457875){sh = "-";ftx = ftx - 6000;}
frxk = frx / 10000;
ftxk = ftx / 10000;
char* byteArray = reinterpret_cast<char*>(&frx); // frequencyen store
for(int i=0;i<4;i++){EEPROM.write(addrf+i,byteArray[i]);}
}
//#################################################
void frequency_transfer()
{
// Protokoll
// AT+DMOSETGROUP=bandwith,Tx-Frequ.,Rx-Frequ.,TX-CTCSS,Squelch,Rx-CTCSS
// AT+DMOSETGROUP=0,145.2750,145.2750,0000,1,0000
Serial.print("AT+DMOSETGROUP="); // begin message but don't send yet..
Serial.print(bw); // bandwith
Serial.print(",");
Serial.print(ftxk,4); // Tx frequency
Serial.print(",");
Serial.print(frxk,4); // Rx frequency
Serial.print(",");
Serial.print(ctcss_t); // Tx CTCSS
Serial.print(",");
Serial.print(squ); // Squelch Level
Serial.print(",");
Serial.println(ctcss_r); // Rx CTCSS
delay(10);
//AT+DMOSETVOLUME=x <CR><LF>
Serial.print("AT+DMOSETVOLUME="); // Volume
Serial.println(l);
delay(10);
//AT+ SETFILTER=PRE/DE-EMPH,Highpass,Lowpass <CR><LF>
Serial.print("AT+SETFILTER="); // Pre/De,Hojpas,Lavpas
Serial.print(Pre_De);
Serial.print(",");
Serial.print(Hojpas);
Serial.print(",");
Serial.println(Lavpas);
}
//###########################################
void frequency_display()
{
display.clearDisplay(); // clears the screen and buffer
display.setTextSize(1.5); // Textsize
display.setTextColor(BLACK);
display.setCursor(0,00);
display.print("Rx");
display.setCursor(15,0); // Courser Horizontal, Vertikal in Pixel
display.print(frxk,4);
display.setCursor(0,10);
display.print("Tx");
display.setCursor(15 ,10); // Courser Horizontal, Vertikal in Pixel
display.print(ftxk,4);
display.setTextSize(1);
display.setCursor(50,20);
display.print("Br.");
display.setCursor(70,20);
display.print(bw_d);
display.setCursor(0,20);
display.print("Pw.");
display.setCursor(22,20);
display.print(power);
display.setCursor(0,30);
display.print("Sh Sq L");
display.setCursor(18,30);
display.print(sh);
display.setCursor(45,30);
display.print(squ);
display.setCursor(74,30);
display.print(l);
display.setCursor(0,40);
display.print("CTCSS Hz");
display.setCursor(36,40);
display.print(ctcssfre);
display.display();
}