Радиолюбительский Маяк на arduino nano

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

RA8JA пишет:

Тоже хорошая идея. Буду пробовать... Надеюсь, что "вибрировать" геркон не будет с частотой 600 Гц...

а чего ему вибрировать если к правильному пину подключить, подключать стандартно как PTT или CW (схема ключика), реле можно и повыше питанием, если есть от чего запитать

Давай самую продвинутую реализовать от DetSimen, он недавно обновил скетч у себя на GIT.

Выход сделан на 13 пин, одновременно моргает светодиод

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

А этот код влезает в ATtiny13
Скетч использует 630 байт (61%) памяти устройства. Всего доступно 1024 байт.
Глобальные переменные используют 110 байт динамической памяти.

//
// Simple Arduino Morse Beacon
// Written by Mark VandeWettering K6HX
// Email: k6hx@arrl.net
// 
// This code is so trivial that I'm releasing it completely without 
// restrictions.  If you find it useful, it would be nice if you dropped
// me an email, maybe plugged my blog @ <a data-cke-saved-href="http://brainwagon.org" href="http://brainwagon.org" rel="nofollow">http://brainwagon.org</a> or included
// a brief acknowledgement in whatever derivative you create, but that's
// just a courtesy.  Feel free to do whatever.
//


struct t_mtab { char c, pat; } ;

struct t_mtab morsetab[] = {
    {'.', 106},
  {',', 115},
  {'?', 76},
  {'/', 41},
  {'A', 6},
  {'B', 17},
  {'C', 21},
  {'D', 9},
  {'E', 2},
  {'F', 20},
  {'G', 11},
  {'H', 16},
  {'I', 4},
  {'J', 30},
  {'K', 13},
  {'L', 18},
  {'M', 7},
  {'N', 5},
  {'O', 15},
  {'P', 22},
  {'Q', 27},
  {'R', 10},
  {'S', 8},
  {'T', 3},
  {'U', 12},
  {'V', 24},
  {'W', 14},
  {'X', 25},
  {'Y', 29},
  {'Z', 19},
  {'1', 62},
  {'2', 60},
  {'3', 56},
  {'4', 48},
  {'5', 32},
  {'6', 33},
  {'7', 35},
  {'8', 39},
  {'9', 47},
  {'0', 63}
} ;

#define N_MORSE  (sizeof(morsetab)/sizeof(morsetab[0]))

#define SPEED  (12)
#define DOTLEN  (1200/SPEED)
#define DASHLEN  (3*(1200/SPEED))

int LEDpin = 3 ;

void
dash()
{
  digitalWrite(LEDpin, HIGH) ;
  delay(DASHLEN);
  digitalWrite(LEDpin, LOW) ;
  delay(DOTLEN) ;
}

void
dit()
{
  digitalWrite(LEDpin, HIGH) ;
  delay(DOTLEN);
  digitalWrite(LEDpin, LOW) ;
  delay(DOTLEN);
}

void
send(char c)
{
  int i ;
  if (c == ' ') {
//    Serial.print(c) ;
    delay(7*DOTLEN) ;
    return ;
  }
  for (i=0; i<N_MORSE; i++) {
    if (morsetab[i].c == c) {
      unsigned char p = morsetab[i].pat ;
 //     Serial.print(morsetab[i].c) ;

      while (p != 1) {
          if (p & 1)
            dash() ;
          else
            dit() ;
          p = p / 2 ;
      }
      delay(2*DOTLEN) ;
      return ;
    }
  }
  /* if we drop off the end, then we send a space */
 // Serial.print("?") ;
}

void
sendmsg(char *str)
{
  while (*str)
    send(*str++) ;
 // Serial.println("");
}

void setup() {
  pinMode(LEDpin, OUTPUT) ;
/*  Serial.begin(9600) ;
  Serial.println("Simple Arduino Morse Beacon v0.0") ;
  Serial.println("Written by Mark VandeWettering <k6hx@arrl.net>") ;
  Serial.println("Check out my blog @ <a data-cke-saved-href="http://brainwagon.org" href="http://brainwagon.org" rel="nofollow">http://brainwagon.org</a>") ;
  Serial.println("") ;
  */
}

void loop() {
  sendmsg("CQ CQ UA6EM/B LN14AF K") ;
  delay(3000) ;
}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Попробовал перевести этот проект маяка излучающего в средневолновом диапазоне на ARDUINO NANO:

Код здесь:

/* AM Morse-Code Transmitter - see http://www.technoblogy.com/show?3QEF

   David Johnson-Davies - www.technoblogy.com - 16th December 2021
   ATtiny85 @ 8 MHz (internal oscillator; BOD disabled)

   CC BY 4.0
   Licensed under a Creative Commons Attribution 4.0 International license:
   http://creativecommons.org/licenses/by/4.0/

   HABR
   https://habr.com/ru/company/ruvds/blog/598955/
*/
// По мотивам под ардуино нано
// Constants
#include <Arduino.h>
#include <RotaryEncoder.h>
#define PIN_IN1 2  // скорость больше
#define PIN_IN2 3  // скорость меньше
RotaryEncoder *encoder = nullptr;

const int Speaker = 11;                   // PB0
const int Antenna = 9;                    // PB1
const int Lamp = 13;                      // PB2
const int Keyer = 3;                      // PB3
const int Auto = 7;                       // PB4
volatile uint8_t Dot = 15;                // Dot duration in 32ths of a second было 6

const char Message[] PROGMEM = "The quick /* brown fox jumps over the lazy dog.*/  ";

uint8_t Chars[48] = {
  //A           B           C           D           E           F
  0b01100000, 0b10001000, 0b10101000, 0b10010000, 0b01000000, 0b00101000,
  //G           H           I           J           K           L
  0b11010000, 0b00001000, 0b00100000, 0b01111000, 0b10110000, 0b01001000,
  //M           N           O           P           Q           R
  0b11100000, 0b10100000, 0b11110000, 0b01101000, 0b11011000, 0b01010000,
  //S           T           U           V           W           X
  0b00010000, 0b11000000, 0b00110000, 0b00011000, 0b01110000, 0b10011000,
  //Y           Z           0           1           2           3
  0b10111000, 0b11001000, 0b11111100, 0b01111100, 0b00111100, 0b00011100,
  //4           5           6           7           8           9
  0b00001100, 0b00000100, 0b10000100, 0b11000100, 0b11100100, 0b11110100,
  //+           ,           -           .           /           ?
  0b01010110, 0b11001110, 0b10000110, 0b01010110, 0b10010100, 0b00110010,
  //&           '           (           )           !           "
  0b10101110, 0b01000100, 0b10110100, 0b10110110, 0b10101110, 0b01001010,
};

// ENCODER ********************************************
void checkPosition()
{
  encoder->tick(); // just call tick() to check the state.
}

// Timer **********************************************

volatile unsigned int GlobalTicks = 0;

// Watchdog interrupt counts ticks (1/32 sec)
ISR (WDT_vect) {
  WDTCSR = WDTCSR | 1 << WDIE;
  GlobalTicks++;
}

// Read ticks without interrupts
unsigned int Ticks () {
  cli(); unsigned int t = GlobalTicks; sei();
  return t;
}

// Wait for n dot durations
void Wait (uint8_t n) {
  unsigned int start = Ticks();
  while (Ticks() - start < Dot * n);
}

// Generate morse **********************************************

// Interrupt modulates carrier at 644Hz
ISR (TIMER2_COMPA_vect) {
  TCCR1B = TCCR1B ^ 1 << CS10;
}

void Beep (bool on) {
  if (on) {
    digitalWrite(Lamp, HIGH);             // LED on
    TCCR2B = 0 << WGM22 | 1 << CS22;      // Clock / 64
  } else {
    digitalWrite(Lamp, LOW);              // LED off
    TCCR2B = 0 << WGM22 | 0 << CS22;      // Clock off
    TCCR1B =  TCCR1B | 1 << CS10;           // Leave carrier on
  }
}

void DotDash (bool dash) {
  Beep(true);
  if (dash) Wait(3); else Wait(1);
  Beep(false);
  Wait(1);
}

void Letter (char letter) {
  uint8_t index;
  letter = letter | 0x20;                 // Convert letters to lower case
  if (letter == ' ') {
    Wait(4);
    return;
  }
  else if (letter >= 'a' && letter <= 'z') index = letter - 'a';
  else if (letter >= '0' && letter <= '9') index = letter - '0' + 26;
  else if (letter >= '+' && letter <= '/') index = letter - '+' + 36;
  else if (letter == '?') index = 41;
  else if (letter >= '&' && letter <= ')') index = letter - '&' + 42;
  else if (letter >= '!' && letter <= '"') index = letter - '!' + 46;
  else return;
  uint8_t code = Chars[index];
  while (code != 0x80) {
    DotDash(code & 0x80);
    code = code << 1;
  }
  Wait(2);
}

// Setup **********************************************

void setup() {
  Serial.begin(115200);
  pinMode(Antenna, OUTPUT);               // Antenna
  pinMode(Speaker, OUTPUT);               // Optional piezo
  pinMode(Lamp, OUTPUT);                  // Optional LED
  pinMode(Keyer, INPUT_PULLUP);           // Morse keyer
  pinMode(Auto, INPUT_PULLUP);            // Transmit message

   // Set up Timer/Counter1 to generate 571kHz (571.42856)(PIN D9)
  // Для тактовой 16 мегагерц
  TCCR1A = 1 << COM1A0;                    // CTC mode to OCR1A
  TCCR1B = 1 << WGM12 | 1 << CS10;        // Clock/1
  OCR1A = 13;                             //

  // Set up Timer/Counter0 to 644Hz (PIN D11)
  TCCR2A = 1 << COM2A0 | 1 << WGM21;      // CTC mode
  TCCR2B = 0 << WGM22 | 1 << CS22;        // Clock / 64
  OCR2A = 193; // было 96;                // Divide by 97
  TIMSK2 = 1 << OCIE2A;                   // Interrupt enabled

  // Set up Watchdog timer for 64Hz interrupt for ticks timer.
  uint8_t _SREG_COPY = SREG;
  noInterrupts();
  WDTCSR = ((1 << WDCE) | (1 << WDE));
  WDTCSR = 0x00;
  WDTCSR = 1 << WDIE;
  SREG = _SREG_COPY;


  // ENCODER ********************************************
  encoder = new RotaryEncoder(PIN_IN1, PIN_IN2, RotaryEncoder::LatchMode::TWO03);
  // register interrupt routine
  attachInterrupt(digitalPinToInterrupt(PIN_IN1), checkPosition, CHANGE);
//  attachInterrupt(digitalPinToInterrupt(PIN_IN2), checkPosition, CHANGE);
}

void loop() {
  // ENCODER ********************************************
  static int pos = 17;
  encoder->tick(); // just call tick() to check the state.

  int newPos = encoder->getPosition();
  if (pos != newPos)
  {
    if (newPos < pos) {
      pos--;// = pos--;
      if(pos < 4) pos = 4;
       }
    if (newPos > pos) {
      pos++;
    if(pos >34) pos = 34;
    }
    encoder->setPosition(pos);
    Dot = pos/2;
    Serial.print("Dot = ");
    Serial.println(Dot);
  } // if

  // Manual mode
  if (digitalRead(Keyer) == 0) Beep(true);
  else Beep(false);
  // Auto mode
  if (digitalRead(Auto) == 0) {
    int p = 0; char c;
    do {
      c = pgm_read_byte(&Message[p++]);
      if (c == 0 || digitalRead(Keyer) == 0) break;
      Letter(c);
    } while (true);
  }
}

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Чо, восстановим наш отоматисский Морзе-маяк?  Я нашёл, кста, где накосорезил, кста, в Tiny85 влезет.  Или уже не актуально?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

DetSimen пишет:

Чо, восстановим наш отоматисский Морзе-маяк?  Я нашёл, кста, где накосорезил, кста, в Tiny85 влезет.  Или уже не актуально?

давай сделаем...

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Строку можно по воздуху получать. Через два JDY-40 с компа на Тиньку