Mjukvara
Programmet är skrivet i Arduino editor som finns att ladda ner gratis. ( https://www.arduino.cc/en/software)
För att kunna programmera medföljande display och radiomodul, behöver man först installera tilläggen för dem.
Dessa hittar man för nedladdning i editorn och längre ner finns en instruktion för detta.
Här nedan finns koden för både VHF och UHF varianterna. Denna går att kopiera och klistra in i editorn för editering.
För befintlig kod lämnas inga garantier att vara helt buggfri, men radion har testats under lång tid och verkar fungera
som tänkt.
För ändringar och uppdateringar, se fliken Uppdateringar.
VHF variant 134-174 MHz
//HAM kit v.1.0 VHF 210524
/* Arduino NANO
Sketch uses 30706 bytes (99%) of program storage space. Maximum is 30720 bytes.
Global variables use 1078 bytes (52%) of dynamic memory, leaving 970 bytes for local variables. Maximum is 2048 bytes.
*/
//RADIO
#include <stdio.h>
#include <SoftwareSerial.h>
#include "DRA818.h"
#include <EEPROM.h>
#define RX 3 // arduino serial RX pin to the DRA818 TX pin
#define TX 4 // arduino serial TX pin to the DRA818 RX pin
int BUTTON = 2;
float TIMEBUTTON;//Tid för långtryck på BUTTON
int count;
int SCAN;
float freq;//Scannerfrekvens
float stime;
float xx;
float RXFREQ = 145.6500;//RX Startfrekvens (MHz)(Om EEPROM är tomt)
float TXFREQ = 145.0500;//TX Startfrekvens (MHz)
uint8_t SQ = 1; //Squelch vid start (0-8)
uint8_t VOL = 4; //Ljudvolym vid start (1-8)
uint8_t CTCSS = 16; //CTCSS kanal vid start (0-38)
uint8_t CTCSSRX;
int MEM; //Menu memory
float timerR;
float timerT;
float TIMEOUT;
String active;
String CTEXT;//Text för CTCSS
int MHZ;
int SAVE;
int eeAddress;
int POWER = 1;
int TONE;
int RXTX;
struct MyObject { //Data som Sparas/Läses från EEPROM
float fieldRX;//RXFREQ
float fieldTX;//TXFREQ
int fieldSQ;
int fieldVOL;
uint8_t fieldCTCSS;
double fieldF0;//RX Minne 0-5...
double fieldF1;
double fieldF2;
double fieldF3;
double fieldF4;
double fieldF5;
double fieldT0;//TX Minne 0-5...
double fieldT1;
double fieldT2;
double fieldT3;
double fieldT4;
double fieldT5;
uint8_t fieldCTCSS0;//CTCSS Minne 0-5...
uint8_t fieldCTCSS1;
uint8_t fieldCTCSS2;
uint8_t fieldCTCSS3;
uint8_t fieldCTCSS4;
uint8_t fieldCTCSS5;
};
SoftwareSerial *dra_serial; // Serial connection to DRA818
DRA818 *dra; // the DRA object once instanciated
double myRX[] = {1456500, 1456000, 1457000, 1568000, 1566500, 1567000}; //RX lista (MHZ*10000)
double myTX[] = {1450500, 1450000, 1451000, 1568000, 1566500, 1567000}; //TX lista
uint8_t myCTCSS[] = {16, 16, 16, 0, 0, 0}; //CTCSS kanallista
int countfreq;//Scanminne
int countmem;//Kanalminne
int pausescan;//Detekterad kanal
//DISPLAY
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin #
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void configure() //Starta upp radio med inställningar
{
dra = new DRA818(dra_serial, DRA818_VHF);
dra->handshake();
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
dra->volume(VOL);
dra->filters(true, true, true);
}
void NEXT() //Nästa menyval
{
TIMEOUT = millis();
timerR = millis();
count++;
MEM = 0;
MHZ = 0;
TIMEBUTTON = millis();
SCAN = 0;
xx = millis();
}
void saving() //Spara inställningar
{
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(35, 12);
if (SCAN > 3)display.print(F("Saved"));
if (SAVE == 1)display.print(F("EEPROM"));
display.display();
delay(500);
}
void setup() {
Serial.begin(9600);
dra_serial = new SoftwareSerial(RX, TX); // Instantiate the Software Serial Object.
//DISP:
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
// Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(35, 12); // Startuptext position
display.print(F("HAM kit v.1.0")); //Startuptext
display.display();
delay(500); //Tid som startuptext visas (ms)
configure();
if (!dra) {
// Serial.println("\nError while configuring DRA818");
}
display.clearDisplay();// Clear the buffer
timerR = millis();
timerT = millis();
pinMode(13, OUTPUT); //Styrning uteffekt H/L
pinMode(BUTTON, INPUT_PULLUP); //Tryckknapp
pinMode(5, INPUT_PULLUP); //VredNER,10-11
pinMode(6, INPUT_PULLUP); //VredUPP, 11-10
digitalWrite(13, POWER); //Sätt utefekt
pinMode(8, OUTPUT); //Ljudförstärkarutgång
pinMode(7, INPUT); //Vid radiosignal, aktivera ljudförstärkarutgång
MyObject customVar; //Variable to store custom object read from EEPROM.
EEPROM.get( eeAddress, customVar );//Läs från EEPROM:
if(customVar.fieldRX>100)//Kontrollera att EEPROM inte är tomt innan inläsning
{
RXFREQ = customVar.fieldRX; //RX Startfrekvens
TXFREQ = customVar.fieldTX; //TX Startfrekvens
SQ = customVar.fieldSQ; //Squelch start
VOL = customVar.fieldVOL; //Ljudvolym start
CTCSS = customVar.fieldCTCSS; //CTCSS start
myRX[0] = customVar.fieldF0; //RX frekvens lista 0-5...
myRX[1] = customVar.fieldF1;
myRX[2] = customVar.fieldF2;
myRX[3] = customVar.fieldF3;
myRX[4] = customVar.fieldF4;
myRX[5] = customVar.fieldF5;
myTX[0] = customVar.fieldT0; //TX frekvens lista 0-5...
myTX[1] = customVar.fieldT1;
myTX[2] = customVar.fieldT2;
myTX[3] = customVar.fieldT3;
myTX[4] = customVar.fieldT4;
myTX[5] = customVar.fieldT5;
myCTCSS[0] = customVar.fieldCTCSS0;//CTCSS lista 0-5...
myCTCSS[1] = customVar.fieldCTCSS1;
myCTCSS[2] = customVar.fieldCTCSS2;
myCTCSS[3] = customVar.fieldCTCSS3;
myCTCSS[4] = customVar.fieldCTCSS4;
myCTCSS[5] = customVar.fieldCTCSS5;
}
freq = RXFREQ; //Startfrekvens scanner
}
void loop() {
if (digitalRead(7) == 0 && VOL != 0) //Vid radiosignal, aktivera ljud
{
digitalWrite(8, HIGH);
}
else digitalWrite(8, LOW);
if (!dra) return; // do nothing if DRA configuration failed
if (digitalRead(BUTTON) != 0)
{
TIMEBUTTON = millis();
}
if (count == 0)active = "VOL"; //VOLMENU
if (count == 1)active = "RX"; //RXMENU
if (count == 2)active = "TX"; //TXMENU
if (count == 3)active = "SCAN"; //SCANMENU
if (count == 4)active = "SQ"; //SQMENU
if (count == 5)active = "CTCSS"; //CTCSSMENU
if (count == 6)active = "EEPROM"; //EEPROMMENU
if (MEM == 0)
{
disp();
MEM = 1;
}
if (digitalRead(5) == 0 && digitalRead(6) == 1 && ((millis() - timerR) > 20)) //Vid vridning moturs (20 ms)
{
TIMEOUT = millis();
if (count == 0) //VOLMENU
{
if (SCAN != 3)
{
VOL -= 1;
if ((VOL < 0) || (VOL > 8))VOL = 0;
if (VOL > 0)dra->volume(VOL);
}
if (SCAN == 3)
{
countmem--;
if (countmem < 0)countmem = 5;
RXFREQ = (float)myRX[countmem] / 10000; //Läs i listan
TXFREQ = (float)myTX[countmem] / 10000;
CTCSS = myCTCSS[countmem];
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
MEM = 0;
}
if (count == 1) //RXMENU
{
double FR = (RXFREQ * 10000);
if (MHZ == 0)FR -= 125; //12.5kHz step
if (MHZ == 1)FR -= 1000;
if (MHZ == 2)FR -= 10000;
if (MHZ == 3)FR -= 100000;
RXFREQ = (float)(FR / 10000), 4;
if (MHZ == 4)TONE = 0;
if (TONE == 0)CTCSSRX = 0;
if (RXTX == 1)TXFREQ = RXFREQ;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 2) //TXMENU
{
double FT = (TXFREQ * 10000);
if (MHZ == 0)FT -= 125; //12.5kHz step
if (MHZ == 1)FT -= 1000;
if (MHZ == 2)FT -= 10000;
if (MHZ == 3)FT -= 100000;
TXFREQ = (float)(FT / 10000), 4;
if (MHZ == 4)POWER = 1;
if (MHZ == 5)RXTX = 0;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 3) //SCANMENU
{
SCAN -= 1;
if (SCAN < 0)SCAN = 0;
MEM = 0;
}
if (count == 4)//SQMENU
{
SQ -= 1;
if ((SQ < 0) || (SQ > 8))SQ = 0;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 5)//CTCSSMENU
{
CTCSS -= 1;
if (CTCSS < 0 || CTCSS == 255)CTCSS = 38; //38
if (TONE == 1)CTCSSRX = CTCSS;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 6)//EEPROMMENU
{
SAVE -= 1;
if (SAVE < 0)SAVE = 1;
MEM = 0;
}
timerR = millis();
}
if (digitalRead(5) == 0 && digitalRead(6) == 0 && ((millis() - timerR) > 20)) //Vid vridning medurs (20 ms)
{
TIMEOUT = millis();
if (count == 0) //VOLMENU
{
if (SCAN != 3)
{
VOL += 1;
if (VOL > 8)VOL = 8;
dra->volume(VOL);
}
if (SCAN == 3)
{
countmem++;
if (countmem > 5)countmem = 0;
RXFREQ = (float)myRX[countmem] / 10000; //Läs i listan
TXFREQ = (float)myTX[countmem] / 10000;
CTCSS = myCTCSS[countmem];
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
MEM = 0;
}
if (count == 1) //RXMENU
{
double FR = (RXFREQ * 10000);
if (MHZ == 0)FR += 125; //12.5kHz step
if (MHZ == 1)FR += 1000;
if (MHZ == 2)FR += 10000;
if (MHZ == 3)FR += 100000;
RXFREQ = (float)(FR / 10000), 4;
if (MHZ == 4)TONE = 1;
if (TONE == 1)CTCSSRX = CTCSS;
if (RXTX == 1)TXFREQ = RXFREQ;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 2)//TXMENU
{
double FT = (TXFREQ * 10000);
if (MHZ == 0)FT += 125; //12.5kHz step
if (MHZ == 1)FT += 1000;
if (MHZ == 2)FT += 10000;
if (MHZ == 3)FT += 100000;
TXFREQ = (float)(FT / 10000), 4;
if (MHZ == 4)POWER = 0;
if (MHZ == 5)RXTX = 1;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 3) //SCANMENU
{
SCAN += 1;
if (SCAN > 9)SCAN = 0;
MEM = 0;
}
if (count == 4)//SQMENU
{
SQ += 1;
if (SQ > 8)SQ = 0;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 5)//CTCSSMENU
{
CTCSS += 1;
if (CTCSS > 38)CTCSS = 0; //38 max
if (TONE == 1)CTCSSRX = CTCSS;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 6)//EEPROMMENU
{
SAVE += 1;
if (SAVE > 1)SAVE = 0;
MEM = 0;
}
timerR = millis();
}
if (count == 1 || count == 2) //RX eller TX
{
if ((digitalRead(BUTTON) == 0) && (millis() - timerT > 500)) //Stega MHz...
{
timerT = millis();
TIMEOUT = millis();
}
if ((millis() - timerT < 399) && ((millis() - xx) > 1200))
{
MHZ++;
if (count == 1 && MHZ > 4)MHZ = 0; //RX
if (MHZ > 5)MHZ = 0;
MEM = 0;
delay(500);
}
}
if ((digitalRead(BUTTON) == 0) && (millis() - TIMEBUTTON) > 1000)
{
NEXT();
digitalWrite(13, POWER); //Sätt uteffekt
if (RXTX == 1)TXFREQ = RXFREQ;
MHZ = 0;
if (SAVE == 1) //Spara i EEPROM?
{
MyObject customVar = {
RXFREQ,
TXFREQ,
SQ,
VOL,
CTCSS,
myRX[0], myRX[1], myRX[2], myRX[3], myRX[4], myRX[5],
myTX[0], myTX[1], myTX[2], myTX[3], myTX[4], myTX[5],
myCTCSS[0], myCTCSS[1], myCTCSS[2], myCTCSS[3], myCTCSS[4], myCTCSS[5]
};
eeAddress = 0;
EEPROM.put(eeAddress, customVar);
saving();
SAVE = 0;
}
}
if (((millis() - TIMEOUT) > 3000) && count != 0)//Vid 3s inaktivitet.
{
count = 0;
MEM = 0;
SAVE = 0;
if (RXTX == 1)TXFREQ = RXFREQ;
digitalWrite(13, POWER); //Sätt utefekt
if (SCAN > 3)
{
myRX[SCAN - 4] = (double)RXFREQ * 10000; //Lagra i listan
myTX[SCAN - 4] = (double)TXFREQ * 10000;
myCTCSS[SCAN - 4] = CTCSS;
saving();
SCAN = 0;
}
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}//
if (count > 6)count = 0; //Efter sista menyn, gå till meny 0.
if (TXFREQ > DRA818_VHF_MAX) TXFREQ = DRA818_VHF_MIN; // when DRA818_VHF_MAX (174.0) is reached, start over at DRA818_VHF_MIN (134.0)
if (TXFREQ < DRA818_VHF_MIN) TXFREQ = DRA818_VHF_MAX;
if (RXFREQ > DRA818_VHF_MAX) RXFREQ = DRA818_VHF_MIN; // when DRA818_VHF_MAX (174.0) is reached, start over at DRA818_VHF_MIN (134.0)
if (RXFREQ < DRA818_VHF_MIN) RXFREQ = DRA818_VHF_MAX;
if (SCAN > 0 && SCAN < 3 && count == 0)SCANNER();
}//Loop
void SCANNER()
{
int nostore = 0;
if (digitalRead(BUTTON) == 0)goto quit;//Gå till nästa kanal vid tryck
if (pausescan == 0 )//&& digitalRead(7) == 1)
{
if (dra->scan(freq))
{
pausescan = 1;
dra->group(DRA818_12K5, freq, TXFREQ, CTCSS, SQ, CTCSSRX);
stime = millis();
if (SCAN == 1)
{
for (int i = 0; i < 5; i++)
{
if ((float)(myRX[i] / 10000) == freq)nostore = 1;
}
if (nostore != 1)
{
myRX[countfreq] = myTX[countfreq] = (double)freq * 10000; //Lagra i listan
countfreq++;
if (countfreq > 5)countfreq = 0;
}
}
}
}//End pausescan
if ((millis() - stime) > 5000)//Om 5 sek har gått, sök vidare
{
quit:
if (SCAN == 1)
{
double FRE = (freq * 10000); //Gör om till double för bättre precision
if (TXFREQ > RXFREQ)
{
FRE += 125; //12.5kHz step
freq = (float)(FRE / 10000), 4;
if (freq > TXFREQ) freq = RXFREQ;
}
if (TXFREQ < RXFREQ)
{
FRE -= 125; //12.5kHz step
freq = (float)(FRE / 10000), 4;
if (freq < TXFREQ) freq = RXFREQ;
}
}
if (SCAN == 2 && pausescan == 0 && digitalRead(7) == 1)//Om signal ej är kvar, sök vidare, annars vänta
{
countfreq++;
if (countfreq > 5)countfreq = 0;
if (myRX[countfreq] >= DRA818_VHF_MIN)freq = (myRX[countfreq] / 10000);
}
disp();
pausescan = 0;
}
}//End scanner
void disp() //Visa i display
{
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0, 0); // Start at top-left corner
String POWERTXT;
String TONETEXT;
if (POWER == 0)POWERTXT = " MHz H";
if (POWER == 1)POWERTXT = " MHz L";
if (TONE == 0)TONETEXT = " MHz ";
if (TONE == 1)TONETEXT = " MHz T";
if (SCAN != 1)display.print(F("RX: "));
if (SCAN == 1)display.print(F("RX1: "));
if (SCAN != 2)display.println(String(RXFREQ, 4) + TONETEXT);
if (SCAN == 2)display.println(String("MEM ") + countfreq);
if (SCAN != 1 && SCAN != 2)display.print(F("TX: "));
if (SCAN == 1)display.print(F("RX2: "));
if (SCAN != 2)display.println(String(TXFREQ, 4) + POWERTXT);
display.setCursor(0, 17);
display.print(String("SQ: ") + String(SQ));
display.setCursor(67, 17);
if (SCAN != 2 && SCAN != 1)display.print(String("CTCSS: ") + String(CTCSS));
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
display.setCursor(0, 25); display.print(String(active));
if (count == 1 || count == 2)
{
if (MHZ == 3)display.print(String(" 10M"));
if (MHZ == 2)display.print(String(" 1M"));
if (MHZ == 1)display.print(String(" 100k"));
if (MHZ == 0)display.print(String(" 12.5k"));
}
if ((count == 2) && (MHZ == 4))display.print(String(" POWER"));
if ((count == 1) && (MHZ == 4))display.print(String(" CTCSS"));
if (count == 3)
{
if (SCAN == 0)display.print(String(" / MEM OFF >"));
if (SCAN == 1)display.print(String(" < SCAN ON >"));
if (SCAN == 2)display.print(String(" < MSCAN >"));
if (SCAN == 3)display.print(String(" < MEM >"));
if ((SCAN >= 4) && (SCAN <= 9))display.print(String(" < STORE ") + (SCAN - 4) + (" >"));
}
if ((count == 2) && (MHZ == 5) && RXTX == 1)display.print(String(" TX=RX"));
if ((count == 2) && (MHZ == 5) && RXTX == 0)display.print(String(" TX=TX"));
display.setTextColor(SSD1306_WHITE); // Draw white text
if (count == 0)
{
display.print(String(" ") + String(VOL));
display.setCursor(45, 25);
if (SCAN == 3)
{
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
display.print(String(" MEM ") + String(countmem));
display.setTextColor(SSD1306_WHITE);
}
if (SCAN == 1 || SCAN == 2) //Fscan/Mscan
{
display.setCursor(75, 24);
display.print(freq, 4);
display.drawRect(72, 22, 55, 10, SSD1306_WHITE);//Rektangel runt frekvens
}
}
display.setCursor(85, 25);
if (CTCSS == 0)CTEXT = " off";
if (CTCSS == 15)CTEXT = " 110.9";
if (CTCSS == 16)CTEXT = " 114.8";
if (CTCSS == 17)CTEXT = " 118.8";/*
if (CTCSS == 18)CTEXT = " 123.0";
if (CTCSS == 19)CTEXT = " 127.3";
if (CTCSS == 20)CTEXT = " 131.8";*/
if ((count == 6) && SAVE == 0)display.print(String("NEXT->"));
if ((count == 6) && SAVE == 1)display.print(String(" SAVE"));
if ((count == 0) && SCAN == 0)display.print(String(CTEXT));
display.display();
}//End Disp
UHF variant 400-470 MHz
//HAM kit v.1.0 UHF 210524
/* Arduino NANO
Sketch uses 30708 bytes (99%) of program storage space. Maximum is 30720 bytes.
Global variables use 1078 bytes (52%) of dynamic memory, leaving 970 bytes for local variables. Maximum is 2048 bytes.
*/
//RADIO
#include <stdio.h>
#include <SoftwareSerial.h>
#include "DRA818.h"
#include <EEPROM.h>
#define RX 3 // arduino serial RX pin to the DRA818 TX pin
#define TX 4 // arduino serial TX pin to the DRA818 RX pin
int BUTTON = 2;
float TIMEBUTTON;//Tid för långtryck på BUTTON
int count;
int SCAN;
float freq;//Scannerfrekvens
float stime;
float xx;
float RXFREQ = 434.6500;//RX Startfrekvens (MHz)(Om EEPROM är tomt)
float TXFREQ = 432.6500;//TX Startfrekvens (MHz)
uint8_t SQ = 1; //Squelch vid start (0-8)
uint8_t VOL = 4; //Ljudvolym vid start (1-8)
uint8_t CTCSS = 16; //CTCSS kanal vid start (0-38)
uint8_t CTCSSRX;
int MEM; //Menu memory
float timerR;
float timerT;
float TIMEOUT;
String active;
String CTEXT;//Text för CTCSS
int MHZ;
int SAVE;
int eeAddress;
int POWER = 1;
int TONE;
int RXTX;
struct MyObject { //Data som Sparas/Läses från EEPROM
float fieldRX;//RXFREQ
float fieldTX;//TXFREQ
int fieldSQ;
int fieldVOL;
uint8_t fieldCTCSS;
double fieldF0;//RX Minne 0-5...
double fieldF1;
double fieldF2;
double fieldF3;
double fieldF4;
double fieldF5;
double fieldT0;//TX Minne 0-5...
double fieldT1;
double fieldT2;
double fieldT3;
double fieldT4;
double fieldT5;
uint8_t fieldCTCSS0;//CTCSS Minne 0-5...
uint8_t fieldCTCSS1;
uint8_t fieldCTCSS2;
uint8_t fieldCTCSS3;
uint8_t fieldCTCSS4;
uint8_t fieldCTCSS5;
};
SoftwareSerial *dra_serial; // Serial connection to DRA818
DRA818 *dra; // the DRA object once instanciated
double myRX[] = {4246000, 4346500, 4347000, 4347250, 4340000, 4215625}; //RX lista (MHZ*10000)
double myTX[] = {4326000, 4326500, 4327000, 4327250, 4340000, 4215625}; //TX lista
uint8_t myCTCSS[] = {16, 16, 16, 0, 0, 0}; //CTCSS kanallista
int countfreq;//Scanminne
int countmem;//Kanalminne
int pausescan;//Detekterad kanal
//DISPLAY
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin #
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
void configure() //Starta upp radio med inställningar
{
dra = new DRA818(dra_serial, DRA818_UHF);
dra->handshake();
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
dra->volume(VOL);
dra->filters(true, true, true);
}
void NEXT() //Nästa menyval
{
TIMEOUT = millis();
timerR = millis();
count++;
MEM = 0;
MHZ = 0;
TIMEBUTTON = millis();
SCAN = 0;
xx = millis();
}
void saving() //Spara inställningar
{
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(35, 12);
if (SCAN > 3)display.print(F("Saved"));
if (SAVE == 1)display.print(F("EEPROM"));
display.display();
delay(500);
}
void setup() {
Serial.begin(9600);
dra_serial = new SoftwareSerial(RX, TX); // Instantiate the Software Serial Object.
//DISP:
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
// Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(35, 12); // Startuptext position
display.print(F("HAM kit v.1.0")); //Startuptext
display.display();
delay(500); //Tid som startuptext visas (ms)
configure();
if (!dra) {
// Serial.println("\nError while configuring DRA818");
}
display.clearDisplay();// Clear the buffer
timerR = millis();
timerT = millis();
pinMode(13, OUTPUT); //Styrning uteffekt H/L
pinMode(BUTTON, INPUT_PULLUP); //Tryckknapp
pinMode(5, INPUT_PULLUP); //VredNER,10-11
pinMode(6, INPUT_PULLUP); //VredUPP, 11-10
digitalWrite(13, POWER); //Sätt utefekt
pinMode(8, OUTPUT); //Ljudförstärkarutgång
pinMode(7, INPUT); //Vid radiosignal, aktivera ljudförstärkarutgång
MyObject customVar; //Variable to store custom object read from EEPROM.
EEPROM.get( eeAddress, customVar );//Läs från EEPROM:
if(customVar.fieldRX>100)//Kontrollera att EEPROM inte är tomt innan inläsning
{
RXFREQ = customVar.fieldRX; //RX Startfrekvens
TXFREQ = customVar.fieldTX; //TX Startfrekvens
SQ = customVar.fieldSQ; //Squelch start
VOL = customVar.fieldVOL; //Ljudvolym start
CTCSS = customVar.fieldCTCSS; //CTCSS start
myRX[0] = customVar.fieldF0; //RX frekvens lista 0-5...
myRX[1] = customVar.fieldF1;
myRX[2] = customVar.fieldF2;
myRX[3] = customVar.fieldF3;
myRX[4] = customVar.fieldF4;
myRX[5] = customVar.fieldF5;
myTX[0] = customVar.fieldT0; //TX frekvens lista 0-5...
myTX[1] = customVar.fieldT1;
myTX[2] = customVar.fieldT2;
myTX[3] = customVar.fieldT3;
myTX[4] = customVar.fieldT4;
myTX[5] = customVar.fieldT5;
myCTCSS[0] = customVar.fieldCTCSS0;//CTCSS lista 0-5...
myCTCSS[1] = customVar.fieldCTCSS1;
myCTCSS[2] = customVar.fieldCTCSS2;
myCTCSS[3] = customVar.fieldCTCSS3;
myCTCSS[4] = customVar.fieldCTCSS4;
myCTCSS[5] = customVar.fieldCTCSS5;
}
freq = RXFREQ; //Startfrekvens scanner
}
void loop() {
if (digitalRead(7) == 0 && VOL != 0) //Vid radiosignal, aktivera ljud
{
digitalWrite(8, HIGH);
}
else digitalWrite(8, LOW);
if (!dra) return; // do nothing if DRA configuration failed
if (digitalRead(BUTTON) != 0)
{
TIMEBUTTON = millis();
}
if (count == 0)active = "VOL"; //VOLMENU
if (count == 1)active = "RX"; //RXMENU
if (count == 2)active = "TX"; //TXMENU
if (count == 3)active = "SCAN"; //SCANMENU
if (count == 4)active = "SQ"; //SQMENU
if (count == 5)active = "CTCSS"; //CTCSSMENU
if (count == 6)active = "EEPROM"; //EEPROMMENU
if (MEM == 0)
{
disp();
MEM = 1;
}
if (digitalRead(5) == 0 && digitalRead(6) == 1 && ((millis() - timerR) > 20)) //Vid vridning moturs (20 ms)
{
TIMEOUT = millis();
if (count == 0) //VOLMENU
{
if (SCAN != 3)
{
VOL -= 1;
if ((VOL < 0) || (VOL > 8))VOL = 0;
if (VOL > 0)dra->volume(VOL);
}
if (SCAN == 3)
{
countmem--;
if (countmem < 0)countmem = 5;
RXFREQ = (float)myRX[countmem] / 10000; //Läs i listan
TXFREQ = (float)myTX[countmem] / 10000;
CTCSS = myCTCSS[countmem];
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
MEM = 0;
}
if (count == 1) //RXMENU
{
double FR = (RXFREQ * 10000);
if (MHZ == 0)FR -= 125; //12.5kHz step
if (MHZ == 1)FR -= 1000;
if (MHZ == 2)FR -= 10000;
if (MHZ == 3)FR -= 100000;
RXFREQ = (float)(FR / 10000), 4;
if (MHZ == 4)TONE = 0;
if (TONE == 0)CTCSSRX = 0;
if (RXTX == 1)TXFREQ = RXFREQ;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 2) //TXMENU
{
double FT = (TXFREQ * 10000);
if (MHZ == 0)FT -= 125; //12.5kHz step
if (MHZ == 1)FT -= 1000;
if (MHZ == 2)FT -= 10000;
if (MHZ == 3)FT -= 100000;
TXFREQ = (float)(FT / 10000), 4;
if (MHZ == 4)POWER = 1;
if (MHZ == 5)RXTX = 0;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 3) //SCANMENU
{
SCAN -= 1;
if (SCAN < 0)SCAN = 0;
MEM = 0;
}
if (count == 4)//SQMENU
{
SQ -= 1;
if ((SQ < 0) || (SQ > 8))SQ = 0;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 5)//CTCSSMENU
{
CTCSS -= 1;
if (CTCSS < 0 || CTCSS == 255)CTCSS = 38; //38
if (TONE == 1)CTCSSRX = CTCSS;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 6)//EEPROMMENU
{
SAVE -= 1;
if (SAVE < 0)SAVE = 1;
MEM = 0;
}
timerR = millis();
}
if (digitalRead(5) == 0 && digitalRead(6) == 0 && ((millis() - timerR) > 20)) //Vid vridning medurs (20 ms)
{
TIMEOUT = millis();
if (count == 0) //VOLMENU
{
if (SCAN != 3)
{
VOL += 1;
if (VOL > 8)VOL = 8;
dra->volume(VOL);
}
if (SCAN == 3)
{
countmem++;
if (countmem > 5)countmem = 0;
RXFREQ = (float)myRX[countmem] / 10000; //Läs i listan
TXFREQ = (float)myTX[countmem] / 10000;
CTCSS = myCTCSS[countmem];
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
MEM = 0;
}
if (count == 1) //RXMENU
{
double FR = (RXFREQ * 10000);
if (MHZ == 0)FR += 125; //12.5kHz step
if (MHZ == 1)FR += 1000;
if (MHZ == 2)FR += 10000;
if (MHZ == 3)FR += 100000;
RXFREQ = (float)(FR / 10000), 4;
if (MHZ == 4)TONE = 1;
if (TONE == 1)CTCSSRX = CTCSS;
if (RXTX == 1)TXFREQ = RXFREQ;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 2)//TXMENU
{
double FT = (TXFREQ * 10000);
if (MHZ == 0)FT += 125; //12.5kHz step
if (MHZ == 1)FT += 1000;
if (MHZ == 2)FT += 10000;
if (MHZ == 3)FT += 100000;
TXFREQ = (float)(FT / 10000), 4;
if (MHZ == 4)POWER = 0;
if (MHZ == 5)RXTX = 1;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 3) //SCANMENU
{
SCAN += 1;
if (SCAN > 9)SCAN = 0;
MEM = 0;
}
if (count == 4)//SQMENU
{
SQ += 1;
if (SQ > 8)SQ = 0;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 5)//CTCSSMENU
{
CTCSS += 1;
if (CTCSS > 38)CTCSS = 0; //38 max
if (TONE == 1)CTCSSRX = CTCSS;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
if (count == 6)//EEPROMMENU
{
SAVE += 1;
if (SAVE > 1)SAVE = 0;
MEM = 0;
}
timerR = millis();
}
if (count == 1 || count == 2) //RX eller TX
{
if ((digitalRead(BUTTON) == 0) && (millis() - timerT > 500)) //Stega MHz...
{
timerT = millis();
TIMEOUT = millis();
}
if ((millis() - timerT < 399) && ((millis() - xx) > 1200))
{
MHZ++;
if (count == 1 && MHZ > 4)MHZ = 0; //RX
if (MHZ > 5)MHZ = 0;
MEM = 0;
delay(500);
}
}
if ((digitalRead(BUTTON) == 0) && (millis() - TIMEBUTTON) > 1000)
{
NEXT();
digitalWrite(13, POWER); //Sätt uteffekt
if (RXTX == 1)TXFREQ = RXFREQ;
MHZ = 0;
if (SAVE == 1) //Spara i EEPROM?
{
MyObject customVar = {
RXFREQ,
TXFREQ,
SQ,
VOL,
CTCSS,
myRX[0], myRX[1], myRX[2], myRX[3], myRX[4], myRX[5],
myTX[0], myTX[1], myTX[2], myTX[3], myTX[4], myTX[5],
myCTCSS[0], myCTCSS[1], myCTCSS[2], myCTCSS[3], myCTCSS[4], myCTCSS[5]
};
eeAddress = 0;
EEPROM.put(eeAddress, customVar);
saving();
SAVE = 0;
}
}
if (((millis() - TIMEOUT) > 3000) && count != 0)//Vid 3s inaktivitet.
{
count = 0;
MEM = 0;
SAVE = 0;
if (RXTX == 1)TXFREQ = RXFREQ;
digitalWrite(13, POWER); //Sätt utefekt
if (SCAN > 3)
{
myRX[SCAN - 4] = (double)RXFREQ * 10000; //Lagra i listan
myTX[SCAN - 4] = (double)TXFREQ * 10000;
myCTCSS[SCAN - 4] = CTCSS;
saving();
SCAN = 0;
}
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}//
if (count > 6)count = 0; //Efter sista menyn, gå till meny 0.
if (TXFREQ > DRA818_UHF_MAX) TXFREQ = DRA818_UHF_MIN; // when DRA818_UHF_MAX (470.0) is reached, start over at DRA818_UHF_MIN (400.0)
if (TXFREQ < DRA818_UHF_MIN) TXFREQ = DRA818_UHF_MAX;
if (RXFREQ > DRA818_UHF_MAX) RXFREQ = DRA818_UHF_MIN; // when DRA818_UHF_MAX (470.0) is reached, start over at DRA818_UHF_MIN (400.0)
if (RXFREQ < DRA818_UHF_MIN) RXFREQ = DRA818_UHF_MAX;
if (SCAN > 0 && SCAN < 3 && count == 0)SCANNER();
}//Loop
void SCANNER()
{
int nostore = 0;
if (digitalRead(BUTTON) == 0)goto quit;//Gå till nästa kanal vid tryck
if (pausescan == 0 )//&& digitalRead(7) == 1)
{
if (dra->scan(freq))
{
pausescan = 1;
dra->group(DRA818_12K5, freq, TXFREQ, CTCSS, SQ, CTCSSRX);
stime = millis();
if (SCAN == 1)
{
for (int i = 0; i < 5; i++)
{
if ((float)(myRX[i] / 10000) == freq)nostore = 1;
}
if (nostore != 1)
{
myRX[countfreq] = myTX[countfreq] = (double)freq * 10000; //Lagra i listan
countfreq++;
if (countfreq > 5)countfreq = 0;
}
}
}
}//End pausescan
if ((millis() - stime) > 5000)//Om 5 sek har gått, sök vidare
{
quit:
if (SCAN == 1)
{
double FRE = (freq * 10000); //Gör om till double för bättre precision
if (TXFREQ > RXFREQ)
{
FRE += 125; //12.5kHz step
freq = (float)(FRE / 10000), 4;
if (freq > TXFREQ) freq = RXFREQ;
}
if (TXFREQ < RXFREQ)
{
FRE -= 125; //12.5kHz step
freq = (float)(FRE / 10000), 4;
if (freq < TXFREQ) freq = RXFREQ;
}
}
if (SCAN == 2 && pausescan == 0 && digitalRead(7) == 1)//Om signal ej är kvar, sök vidare, annars vänta
{
countfreq++;
if (countfreq > 5)countfreq = 0;
if (myRX[countfreq] >= DRA818_UHF_MIN)freq = (myRX[countfreq] / 10000);
}
disp();
pausescan = 0;
}
}//End scanner
void disp() //Visa i display
{
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0, 0); // Start at top-left corner
String POWERTXT;
String TONETEXT;
if (POWER == 0)POWERTXT = " MHz H";
if (POWER == 1)POWERTXT = " MHz L";
if (TONE == 0)TONETEXT = " MHz ";
if (TONE == 1)TONETEXT = " MHz T";
if (SCAN != 1)display.print(F("RX: "));
if (SCAN == 1)display.print(F("RX1: "));
if (SCAN != 2)display.println(String(RXFREQ, 4) + TONETEXT);
if (SCAN == 2)display.println(String("MEM ") + countfreq);
if (SCAN != 1 && SCAN != 2)display.print(F("TX: "));
if (SCAN == 1)display.print(F("RX2: "));
if (SCAN != 2)display.println(String(TXFREQ, 4) + POWERTXT);
display.setCursor(0, 17);
display.print(String("SQ: ") + String(SQ));
display.setCursor(67, 17);
if (SCAN != 2 && SCAN != 1)display.print(String("CTCSS: ") + String(CTCSS));
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
display.setCursor(0, 25); display.print(String(active));
if (count == 1 || count == 2)
{
if (MHZ == 3)display.print(String(" 10M"));
if (MHZ == 2)display.print(String(" 1M"));
if (MHZ == 1)display.print(String(" 100k"));
if (MHZ == 0)display.print(String(" 12.5k"));
}
if ((count == 2) && (MHZ == 4))display.print(String(" POWER"));
if ((count == 1) && (MHZ == 4))display.print(String(" CTCSS"));
if (count == 3)
{
if (SCAN == 0)display.print(String(" / MEM OFF >"));
if (SCAN == 1)display.print(String(" < SCAN ON >"));
if (SCAN == 2)display.print(String(" < MSCAN >"));
if (SCAN == 3)display.print(String(" < MEM >"));
if ((SCAN >= 4) && (SCAN <= 9))display.print(String(" < STORE ") + (SCAN - 4) + (" >"));
}
if ((count == 2) && (MHZ == 5) && RXTX == 1)display.print(String(" TX=RX"));
if ((count == 2) && (MHZ == 5) && RXTX == 0)display.print(String(" TX=TX"));
display.setTextColor(SSD1306_WHITE); // Draw white text
if (count == 0)
{
display.print(String(" ") + String(VOL));
display.setCursor(45, 25);
if (SCAN == 3)
{
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
display.print(String(" MEM ") + String(countmem));
display.setTextColor(SSD1306_WHITE);
}
if (SCAN == 1 || SCAN == 2) //Fscan/Mscan
{
display.setCursor(75, 24);
display.print(freq, 4);
display.drawRect(72, 22, 55, 10, SSD1306_WHITE);//Rektangel runt frekvens
}
}
display.setCursor(85, 25);
if (CTCSS == 0)CTEXT = " off";
if (CTCSS == 15)CTEXT = " 110.9";
if (CTCSS == 16)CTEXT = " 114.8";
if (CTCSS == 17)CTEXT = " 118.8";/*
if (CTCSS == 18)CTEXT = " 123.0";
if (CTCSS == 19)CTEXT = " 127.3";
if (CTCSS == 20)CTEXT = " 131.8";*/
if ((count == 6) && SAVE == 0)display.print(String("NEXT->"));
if ((count == 6) && SAVE == 1)display.print(String(" SAVE"));
if ((count == 0) && SCAN == 0)display.print(String(CTEXT));
display.display();
}//End Disp
Instruktion för att installera tillägg i Arduino editorn:
För att kunna programmera display och radiodel, behövs följande tillägg installeras i Arduino programvara.
Gå till ”Hantera bibliotek”...
Display: Sök efter ”SSD1306” och installera sedan ”Adafruit SSD1306”...
Radio: Sök även efter ”DRA818” och installera ”DRA818”...
Nu finns exempelfiler att köra och display och radiodel går nu att programmera.