Ecco un semplicissimo beacon da realizzare con Arduino ed una schedina con il chip SI5351 capace di emettere segnali da 8 kHz fino a 160MHz con una potenza di 10 mW
lo schema di montaggio è il seguente, l'uscita dell'RF cui collegare l'antenna è la CLK0
ATTENZIONE E' D'OBBLIGO UN FILTRO PER LA BANDA CUI SI UTILIZZERA' IL BEACON
#include <Wire.h>
#include <Adafruit_SI5351.h>
Adafruit_SI5351 clockgen = Adafruit_SI5351();
int LEDpin = 13 ;
#define SPEED (11) //12 velocita' cw in WPM. Default: 16
#define DOTLEN (1200/SPEED) //1200
#define DASHLEN (3*(1200/SPEED)) //1200
#define PAUSE 15// tempo durata portante fissa tx (15)
#define ENCODER_A 3 // Encoder pin A
#define ENCODER_B 2 // Encoder pin B
#define ENCODER_BTN 4 // Encoder c button
void sendMsg(char*);
void Msg(char);
void dash();
void dot();
int giro = 1;
///////////////////////////
unsigned long previousMillis = 0; //will store last time LED was updated
unsigned long interval = 1000; //interval at which to blink (milliseconds)
///////////////////////////
char str[230]; // = "";
volatile uint32_t vfo = 144450000; //12034116;// 144419000 metti la frequenza hz iniziale in questo punto(es. 28225000//50425//144450...)
uint32_t pllFreq; // si5351 internal vco frequency
uint32_t radix = 1000; // start step size 12.5kHz
uint32_t si5351multiCount; // Multicounter
uint32_t si5351multi_int; // Multicounter integer
uint32_t si5351nomi; // Multicounter nominator
uint32_t si5351denomi = 1000000; // Multicounter denominator one million
uint32_t si5351divider; // VCO output divider integer part
boolean changed_f = 1;
String tbfo = "";
/**************************************/
/* Displays the frequency */
/**************************************/
void count_frequency()
{
uint16_t f, g;
f = vfo / 1000000; //variable is now vfo instead of 'frequency' vfo esim 145787500
si5351divider = 900000000/vfo; // vfo divider integer
pllFreq = si5351divider * vfo; // counts pllFrequency
si5351multiCount = pllFreq / 25; // feedback divider
si5351multi_int = pllFreq / 25000000; // feedback divider integer
si5351nomi = si5351multiCount % 1000000; // feedback divider integer
si5351denomi = 1000000; // feedback divider fraktion
Serial.print(" vfo ");
Serial.println( vfo);
Serial.print(" pllFreq ");
Serial.println( pllFreq);
Serial.print("si5351divider ");
Serial.println(si5351divider);
Serial.print(" si5351multiCount ");
Serial.println(si5351multiCount);
Serial.print(" si5351multi_int ");
Serial.println(si5351multi_int);
Serial.print(" si5351nomi ");
Serial.println(si5351nomi);
Serial.print(" si5351denomi ");
Serial.println(si5351denomi);
}
/**************************************/
/* Displays the frequency change step */
/**************************************/
void display_radix()
{
switch (radix)
{
}
Serial.println("radix");
Serial.println(radix);
}
/**************************************/
/* Interrupt service routine for */
/* encoder frequency change */
/**************************************/
ISR(PCINT2_vect){
set_frequency(1);
set_frequency(-1);
}
/**************************************/
/* Change the frequency */
/* dir = 1 Increment */
/* dir = -1 Decrement */
/**************************************/
void set_frequency(short dir)
{
if (dir == 1)
vfo += radix;
if (dir == -1)
vfo -= radix;
if(vfo > 170000000)
vfo = 100000;
if(vfo < 100000)
vfo = 150000000;
if (vfo < 0)
vfo = 100000;
changed_f = 1;
}
void dash()
{
digitalWrite(LEDpin, HIGH) ;
clockgen.enableOutputs(true);
delay(DASHLEN);
digitalWrite(LEDpin, LOW) ;
clockgen.enableOutputs(false);
delay(DOTLEN);
}
void dot()
{
digitalWrite(LEDpin, HIGH) ;
clockgen.enableOutputs(true);
delay(DOTLEN);
digitalWrite(LEDpin, LOW) ;
clockgen.enableOutputs(false);
delay(DOTLEN);
}
void setup(void)
{
delay(2000); //2seconds
Wire.begin();
/* Initialise the sensor */
if (clockgen.begin() != ERROR_NONE)
{
while(1);
}
/* Enable the clocks */
clockgen.enableOutputs(true);
pinMode(ENCODER_BTN, INPUT_PULLUP);
PCICR |= (1 << PCIE2); // Enable pin change interrupt for the encoder
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
sei();
count_frequency(); // Count f and update the display
}
void loop(void)
{
if (previousMillis/1000 > 1)
{
//// Da commentare per usarlo come generatore
strcat (str, "VVV DE XXXXX/B JN65DV XXXXX/B JN65DV PSE QSL "); //testo messaggio da trasmettere(rispettare gli spazi=pausa)
sendMsg( str ); // messaggio da inviare!
/////
}
else {
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis; //save the last time you blinked the LED
}
}
// Update the display if the frequency has been changed
if (changed_f)
{
///clockgen.setupPLL(SI5351_PLL_B, (si5351multi_int),(si5351nomi),(si5351denomi)); // write si5351ctl divider word
clockgen.setupPLL(SI5351_PLL_A, (si5351multi_int),(si5351nomi),(si5351denomi)); // write si5351ctl divider word
// clockgen.setupMultisynthInt(0, SI5351_PLL_A, SI5351_MULTISYNTH_DIV_6);
clockgen.setupMultisynth(0, SI5351_PLL_A,(si5351divider),0,1 );
///clockgen.setupMultisynth(0, SI5351_PLL_B,(si5351divider),0,1 );
changed_f = 0;
}
{
giro = 3;
switch (radix)
{
case 100:
radix = 1000;
break;
case 1000:
radix = 12500;
break;
case 12500:
radix = 100000;
break;
case 100000:
radix = 1000000;
break;
case 1000000:
radix = 10000000;
break;
case 10000000:
radix = 100;
break;
}
display_radix();
}
}
void sendMsg(char *str)
{
int i;
delay(500);
for(i=0;i<strlen(str);i++)
{
switch (str[i])
{
case 'A':
dot();dash();break;
case 'B':
dash();dot();dot();dot();break;
case 'C':
dash();dot();dash();dot();break;
case 'D':
dash();dot();dot();break;
case 'E':
dot();break;
case 'F':
dot();dot();dash();dot();break;
case 'G':
dash();dash();dot();break;
case 'H':
dot();dot();dot();dot();break;
case 'I':
dot();dot();break;
case 'J':
dot();dash();dash();dash();break;
case 'K':
dash();dot();dash();break;
case 'L':
dot();dash();dot();dot();break;
case 'M':
dash();dash();break;
case 'N':
dash();dot();break;
case 'O':
dash();dash();dash();break;
case 'P':
dot();dash();dash();dot();break;
case 'Q':
dash();dash();dot();dash();break;
case 'R':
dot();dash();dot();break;
case 'S':
dot();dot();dot();break;
case 'T':
dash();break;
case 'U':
dot();dot();dash();break;
case 'V':
dot();dot();dot();dash();break;
case 'W':
dot();dash();dash();break;
case 'X':
dash();dot();dot();dash();break;
case 'Y':
dash();dot();dash();dash();break;
case 'Z':
dash();dash();dot();dot();break;
case ' ':
// tone(tonePin, 21000);
delay(DOTLEN*5);
// noTone(tonePin);
break;
case '.':
dot();dash();dot();dash();dot();dash();break;
case ',':
dash();dash();dot();dot();dash();dash();break;
case ':':
dash();dash();dash();dot();dot();break;
case '?':
dot();dot();dash();dash();dot();dot();break;
case '\'':
dot();dash();dash();dash();dash();dot();break;
case '-':
dash();dot();dot();dot();dot();dash();break;
case '/':
dash();dot();dot();dash();dot();break;
case '(':
case ')':
dash();dot();dash();dash();dot();dash();break;
case '\"':
dot();dash();dot();dot();dash();dot();break;
case '@':
dot();dash();dash();dot();dash();dot();break;
case '=':
dash();dot();dot();dot();dash();break;
case '0':
dash();dash();dash();dash();dash();break;
case '1':
dot();dash();dash();dash();dash();break;
case '2':
dot();dot();dash();dash();dash();break;
case '3':
dot();dot();dot();dash();dash();break;
case '4':
dot();dot();dot();dot();dash();break;
case '5':
dot();dot();dot();dot();dot();break;
case '6':
dash();dot();dot();dot();dot();break;
case '7':
dash();dash();dot();dot();dot();break;
case '8':
dash();dash();dash();dot();dot();break;
case '9':
dash();dash();dash();dash();dot();break;
}
// Serial.print(str[i]);
delay(2*DOTLEN);
}
// pulisce al stringa con tutti i terminatori di fine riga
memset( str, '\0', strlen( str ) );
//accende la nota
clockgen.enableOutputs(true);
//portante x secondi
delay(PAUSE*1000);
//spegne la portante
clockgen.enableOutputs(false);
// tempo di bianco
delay(PAUSE*400);
}