Uppdateringar
Uppdateringar
Här finns programuppdateringar, programexempel och även ombyggnadsalternativ.
Programkoderna kopieras och klistras in i Arduino editorn för uppdatering av programmet.
Sidan kommer att uppdateras när nya varianter dyker upp.
MJUKVARA
HAMkit ver. 1.1
- Ljudavbrott var 5 sek. vid minnesscanning åtgärdat.
- CTCSS frekvensvisning borttagen p.g.a. minnesbrist efter programändring.
- Buggfix vid läsning från EEPROM.
(Vid inläsning av ny RX & TX frekvens från EEPROM ändrades tidigare bara visningen i displayen
men inte den valda frekvensen)
VHF variant 134-174 MHz ver.1.1
//HAM kit v.1.1 VHF 210118
/* Arduino NANO
Sketch uses 30656 bytes (99%) of program storage space. Maximum is 30720 bytes.
Global variables use 1046 bytes (51%) of dynamic memory, leaving 1002 bytes for local variables. Maximum is 2048 bytes.
V.1.1: Scanner ändrad. CTCSS frekvensvisning borttagen. Buggfix EEPROM.
*/
//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;
float stime;
float xx;
float RXFREQ = 145.7500;//RX Startfrekvens (MHz)(Om EEPROM är tomt)
float TXFREQ = 145.1500;//TX Startfrekvens (MHz)
int SCAN;
float freq = RXFREQ;//Scannerfrekvens
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.1")); //Startuptext
display.display();
delay(500); //Tid som startuptext visas (ms)
//configure();
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
// pinMode(12, OUTPUT); //Aktivera sändning
//digitalWrite(12, 0); //Sätt utefekt
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;
}
configure();
}
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 (50 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 (50 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 (freq < RXFREQ) freq = TXFREQ;
}
if (TXFREQ < RXFREQ)
{
FRE -= 125; //12.5kHz step
freq = (float)(FRE / 10000), 4;
if (freq < TXFREQ) freq = RXFREQ;
// if (freq > RXFREQ) freq = TXFREQ;
}
pausescan=0;
}
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);
}
if(digitalRead(7) == 1)pausescan = 0;
disp();
}
}//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 ((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 ver.1.1
//HAM kit v.1.1 UHF 210118
/* Arduino NANO
Sketch uses 30658 bytes (99%) of program storage space. Maximum is 30720 bytes.
Global variables use 1046 bytes (51%) of dynamic memory, leaving 1002 bytes for local variables. Maximum is 2048 bytes.
V.1.1: Scanner ändrad. CTCSS frekvensvisning borttagen. Buggfix EEPROM.
*/
//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;
float stime;
float xx;
float RXFREQ = 434.6500;//RX Startfrekvens (MHz)(Om EEPROM är tomt)
float TXFREQ = 432.6500;//TX Startfrekvens (MHz)
int SCAN;
float freq = RXFREQ;//Scannerfrekvens
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[] = {4346000, 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.1")); //Startuptext
display.display();
delay(500); //Tid som startuptext visas (ms)
//configure();
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
// pinMode(12, OUTPUT); //Aktivera sändning
//digitalWrite(12, 0); //Sätt utefekt
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;
}
configure();
}
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 (50 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 (50 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 (freq < RXFREQ) freq = TXFREQ;
}
if (TXFREQ < RXFREQ)
{
FRE -= 125; //12.5kHz step
freq = (float)(FRE / 10000), 4;
if (freq < TXFREQ) freq = RXFREQ;
// if (freq > RXFREQ) freq = TXFREQ;
}
pausescan=0;
}
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);
}
if(digitalRead(7) == 1)pausescan = 0;
disp();
}
}//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 ((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
Programexempel VHF
Här är en lite enklare och förkortad VHF programversion med fler kommentarer i koden. Koden är gjord som exempel.
Grundinställningar står med fet stil i koden.
Sändar- och mottagarfrekvens är här densamma.
Frekvens visas med större text i displayen.
Endast ljudvolym och frekvens kan ändras med vredet.
Det är ej möjligt att scanna eller spara i EEPROM.
Ingen kanallista finns.
Programkod:
//HAM kit v.1.0 VHF EXEMPEL
/* Arduino NANO
Sketch uses 23692 bytes (77%) of program storage space. Maximum is 30720 bytes.
Global variables use 783 bytes (38%) of dynamic memory, leaving 1265 bytes for local variables. Maximum is 2048 bytes.
*/
//RADIO
#include <stdio.h>
#include <SoftwareSerial.h>
#include "DRA818.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; //Menyräknare
float xx;
//Grundinställningar:
float RXFREQ = 145.2500;//RX Startfrekvens (MHz)
float TXFREQ = RXFREQ; //TX Startfrekvens (MHz)
uint8_t SQ = 1; //Squelch (0-8)
uint8_t VOL = 4; //Ljudvolym vid uppstart (1-8)
uint8_t CTCSS = 0; //CTCSS kanal (0-38)
int POWER = 1;//Uteffekt. 1=Låg. 0=Hög.
int MEM; //Menu memory (Håller koll på om meny är aktiv)
float timerR;
float timerT;
float TIMEOUT;
String active;
int MHZ;
int SAVE;
SoftwareSerial *dra_serial; // Serial connection to DRA818
DRA818 *dra; // the DRA object once instanciated
//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, CTCSS);
dra->volume(VOL);
dra->filters(true, true, true);
}
void NEXT() //Nästa menyval
{
TIMEOUT = millis();
timerR = millis();
count++;
MEM = 0;
MHZ = 0;
TIMEBUTTON = millis();
xx = millis();
}
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, 8); // Startuptext 1 position
display.println(F("HAM kit VHF Ex.")); //Startuptext 1
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
}
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 = "FREQ"; //RXMENU
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
{
VOL -= 1;
if ((VOL < 0) || (VOL > 8))VOL = 0;
if (VOL > 0)dra->volume(VOL);
MEM = 0;
}
if (count == 1) //Frekvensmeny
{
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;
TXFREQ = RXFREQ;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSS);
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
{
VOL += 1;
if (VOL > 8)VOL = 8;
dra->volume(VOL);
MEM = 0;
}
if (count == 1) //Frekvensmeny
{
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;
TXFREQ = RXFREQ;
MEM = 0;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSS);
}
timerR = millis();
}
if (count == 1) //Frekvensmeny
{
if ((digitalRead(BUTTON) == 0) && (millis() - timerT > 500)) //Stega MHz...
{
timerT = millis();
TIMEOUT = millis();
}
if ((millis() - timerT < 399) && ((millis() - xx) > 1200))
{
MHZ++;
if (MHZ > 3)MHZ = 0;//Efter 10MHz, välj 12,5kHz
MEM = 0;
delay(500);
}
}
if ((digitalRead(BUTTON) == 0) && (millis() - TIMEBUTTON) > 1000)//Vid 1s.tryck på knapp
{
NEXT();
MHZ = 0;
}
if (((millis() - TIMEOUT) > 3000) && count != 0)//Vid 3s inaktivitet.
{
count = 0;
MEM = 0;
}
if (count > 1)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;
}//Loop
void disp() //Visa i display
{
display.clearDisplay();
display.setTextSize(2); // Big 2:2 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0, 0); // Start at top-left corner
display.print(String(RXFREQ, 4));
display.setTextSize(1); // Normal 1:1 pixel scale
display.print(String(" MHz"));
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
display.setCursor(0, 25);
display.print(String(active));
if (count == 1)
{
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"));
}
display.setTextColor(SSD1306_WHITE); // Draw white text
if (count == 0)
{
display.print(String(" ") + String(VOL));
}
display.display();
}//End Disp
Programexempel UHF
Här är en UHF scanner som styrs med endast tryckknappen. Vid uppstart väljs en TX , RX frekvens och CTCSS, men efter ett tryck
på knappen hoppar den till kanallistan. Sedan vid varje tryck (1 s.) växlar den mellan att scanna hela kanallistan eller stega mellan kanalerna. Stegning görs med korta tryck.
Inställningar såsom frekvenser, ljudvolym och squelch är fasta. -Ljudvolymen kan ju alltid justeras med potentiometern.
I exemplet är 12 kanaler inlagda i RX listan, men upp till 99 kan läggas in.
Sändar- och mottagarfrekvens är här densamma förutom vid uppstart.
Frekvens visas med större text i displayen.
Inställningar görs i programkoden.
Det är ej möjligt att spara i EEPROM.
Denna scanner är ljudlös vid scanning (Inget brus hörs vid frekvensbyte).
Programkod:
//MiniRF v.1.0 UHF
/*
Sketch uses 22446 bytes (73%) of program storage space. Maximum is 30720 bytes.
Global variables use 825 bytes (40%) of dynamic memory, leaving 1223 bytes for local variables. Maximum is 2048 bytes.
*/
//RADIO
#include <stdio.h>
#include <SoftwareSerial.h>
#include "DRA818.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 stime;
float RXFREQ = 434.6500;//RX Startfrekvens (MHz)
float TXFREQ = 432.6500;//TX Startfrekvens (MHz)
uint8_t SQ = 2; //Squelch vid start (0-8)
uint8_t VOL = 8; //Ljudvolym vid start (1-8)
uint8_t CTCSS = 16; //CTCSS kanal vid start (0-38)
uint8_t CTCSSRX;
int POWER = 1; //Uteffekt. 0=Hög 1=Låg.
int MEM; //Menu memory
float timerR;
float TIMEOUT;
int noofchan=12; //Antal kanaler som används i RX listan (Nu 12 men kan fyllas på med max 99)
SoftwareSerial *dra_serial; // Serial connection to DRA818
DRA818 *dra; // the DRA object once instanciated
double myRX[] = {4460063, 4460188,4460313, 4460438, 4460563, 4460688, 4460813, 4460938, 4346000, 4346500, 4346875, 4215625}; //RX lista (MHZ*10000)
/*
PMR kanaler:
Kanal 1 – 446,00625 MHz
Kanal 2 – 446,01875 MHz
Kanal 3 – 446,03125 MHz
Kanal 4 – 446,04375 MHz
Kanal 5 – 446,05625 MHz
Kanal 6 – 446,06875 MHz
Kanal 7 – 446,08125 MHz
Kanal 8 – 446,09375 MHz
*/
int countfreq;//Scanminne
int countmem=-1;//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;
TIMEBUTTON = millis();
if(count==1)
{
SCAN=1;
}
else SCAN=0;
}
void senddata()
{
countmem++;
if (countmem > noofchan-1)countmem = 0;
RXFREQ = (float)myRX[countmem] / 10000; //Läs i listan
TXFREQ = RXFREQ;
dra->group(DRA818_12K5, RXFREQ, TXFREQ, CTCSS, SQ, CTCSSRX);
}
void setup() {
Serial.begin(9600);
dra_serial = new SoftwareSerial(RX, TX); // Instantiate the Software Serial Object.
configure();
if (!dra) {
Serial.println("\nError while configuring DRA818");
}
timerR = millis();
pinMode(BUTTON, INPUT_PULLUP); //Tryckknapp
pinMode(7, INPUT); //Signal
pinMode(8, OUTPUT); //Ljudförstärkarutgång
pinMode(13, OUTPUT); //Styrning uteffekt H/L
digitalWrite(13, POWER); //Sätt uteffekt
//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(30, 8); // Startuptext 1 position
display.println(F("HAM kit UHF RX")); //Startuptext 1
display.display();
delay(500); //Tid som startuptext visas (ms)
display.clearDisplay();// Clear the buffer
}
void loop() {
if (!dra) return; // do nothing if DRA configuration failed
if (digitalRead(7) == 0) //Vid radiosignal, aktivera ljud
{
digitalWrite(8, HIGH);
}
else digitalWrite(8, LOW);
if (digitalRead(BUTTON) != 0)
{
TIMEBUTTON = millis();
}
if (MEM == 0)
{
disp();
MEM = 1;
}
if (digitalRead(BUTTON) == 0 && ((millis() - timerR) > 60)) //Vid tryck på knappen (60 ms)
{
TIMEOUT = millis();
if (count == 0) //VOLMENU
{
if (SCAN == 0)
{
senddata();
delay(20);
}
MEM = 0;
}
timerR = millis();
}
if ((digitalRead(BUTTON) == 0) && (millis() - TIMEBUTTON) > 1000)//Vid 1s tryck på knappen
{
NEXT();
}
if (count > 1)count = 0; //Efter sista menyn, gå till meny 0.
if (SCAN == 1 && count == 1)SCANNER();
}//Loop
void SCANNER()
{
int nostore = 0;
if (digitalRead(BUTTON) == 0)goto quit;//Gå till nästa kanal vid tryck
if (pausescan == 0 )
{
if (digitalRead(7) == 0)
{
pausescan = 1;
stime = millis();
}
}//End pausescan
if ((millis() - stime) > 5000)//Om 5 sek har gått, sök vidare
{
// quit:
if (SCAN == 1 && pausescan == 0 && digitalRead(7) == 1)//Om signal ej är kvar, sök vidare, annars vänta (7) && pausescan == 0
{
quit:
senddata();
delay(100);
MEM=0;
pausescan = 0;
}
pausescan = 0;
}
}//End scanner
void disp() //Visa i display
{
display.clearDisplay();
display.setTextSize(2,4); // Big 2:2 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(0, 0); // Start at top-left corner
display.print(String(RXFREQ, 4));
display.setTextSize(1); // Normal 1:1 pixel scale
if(SCAN==0)
{
display.print(String(" MHz"));
if(TXFREQ!=RXFREQ)display.print(String("-")); //Visa "-" om inte TX och RX frekvens är densamma.
}
else display.print(String(" SCAN"));
display.setCursor(100,14);//(110, 14);
display.setTextSize(2,2);
if(countmem==-1) display.print(String(CTCSS)); //Visa CTCSS kanal vid uppstart.
if((countmem+1)<10&&countmem>-1) display.print(String("0"));
if(countmem>-1)display.print(String(countmem+1));
//display.drawRect(107, 12, 16, 18, SSD1306_WHITE);//Rektangel runt kanal 0-9
display.drawRect(98, 12, 26, 18, SSD1306_WHITE);//Rektangel runt kanal 10-99
display.display();
}//End Disp
HÅRDVARA
LJUDFÖRSTÄRKARE:
För att få full spänning till ljudförstärkarkretsen som enligt manual matas med min. 4V, kan ett relä
kopplas in på Arduinons utgång 8 som i sin tur fördelar ut matningsspänningen till kretsens pin 6.
Detta kan vara ett 5V miniatyrrelä som inte tar stor plats och ljudet riskerar då inte att förvrängas om utgångens
spänning blir för låg för att mata förstärkarkretsen.