Arduino - SI5351 very simple  CW beacon

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);

}

Flag Counter
Flag Counter