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

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

DetSimen пишет:

нууу, у мня идей больше неть.  бери, значить, другой код маяка. 

Не!!! "Русские не сдаются"!!!
Я тут явную связь выявил, стоит открыть-закрыть монитор порта и скетч начинает работать правильно...
 

уменьшил скорость порта до 9600, пытаю, пока работает как надо, теперь надо строку вводимую в мониторе порта сохранить в еепром и забирать оттуда, если было сохранение, попробую сам прикрутить

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

Нуууу... моё скудоумие дальше не простираеца

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

DetSimen пишет:
Нуууу... моё скудоумие дальше не простираеца

не прибедняйся, ты это написал )))
 

нет, всё таки пропускает, просто сейчас вылетают пробелы...
значит непонятно...
Тут без ЕвгенийП не обойтись, у него глаз намётан )))

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

думаю, не будуть корифеи в этом дедокоде разбираца.  просто возьми другой маяк, рабочий. 

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

DetSimen пишет:

думаю, не будуть корифеи в этом дедокоде разбираца.  просто возьми другой маяк, рабочий. 

так он рабочий, если регулировку скорости в loop переносишь...мы же хотели по фэншую

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

Я б забил. Не работает - фтопку. Наливать незашто. 

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

Тебе нада нанять прафессионалоф, наерна. Как бы я не тщился, выше ровных извилин не прыгну. :-)

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

DetSimen пишет:

Тебе нада нанять прафессионалоф, наерна. Как бы я не тщился, выше ровных извилин не прыгну. :-)

это не то изделие, где требуется наёмная рабочая сила )))
максимум - налить...

...не могу понять... и это мотивирует )))

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

DetSimen пишет:

нууу, у мня идей больше неть.  бери, значить, другой код маяка. 

вот эту строчку проверь внимательно, нет ли ашыбок

006 #pragma GCC otimize ("-Os") //где х - 0, 1, 2, 3, fast, g, s - уровень оптимизации

ты и default потерял в 219 строчке.  

конец перепишы вот так

	case msg_ReadSensor: {
		uint8_t newdottime = 100 - 5*(analogRead(mySpeedPin)>>6); // тут все твои чтения и вычисления
		if (newdottime != DOT_TIME) {   // меняем ТОЛЬКО если значения РЕАЛЬНО ИЗМЕНИЛИСЬ
			DOT_TIME = newdottime;
			DASH_TIME = 3 * DOT_TIME;
			Serial.print("Скорость = ");
			Serial.println(newdottime);
		}
		break;
	}
	default:
	 Serial.print("Unknown message code: 0x"); Serial.println(msg.Message, HEX);
     break;
	}

 

строчку кстати исправил - #pragma GCC optimize ("-Os") //где х - 0, 1, 2, 3, fast, g, s - уровень оптимизации

Да, цикл loop выполняется за время от 18 миллисекунд при настройке сериала на скорость 9600 до 1 миллисекунды и менее при повышении скорости порта, попробую в таймере уменьшить время опроса датчика  до к примеру 13 миллисекнд, по результатам отпишусь...
Всё таки хотелось бы выяснить в чем проблема, что на четвётом таймере библиотека или скетч заглючили, по сути у тебя получилась некая версия RTOS на таймерах и, это интересно

 

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

в моих подделках, до 9 таймеров вместе не глючили, хоть и пересекались.  Или я просто не замечал.... 

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

DetSimen пишет:

в моих подделках, до 9 таймеров вместе не глючили, хоть и пересекались.  Или я просто не замечал.... 

ну так то были поделки, а здесь только с виду простейшая задача

при опросе аналогового датчика каждые 13 миллисекунд еще хуже

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

короче, забей.   Я- всё, забил. Хватить. 

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

DetSimen пишет:

короче, забей.   Я- всё, забил. Хватить. 

не маяком единым...мне нравица сама идея библиотеки...

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

чуть протрезвею, и из этой темы все свои сапщения самоликвидирую.  

Как правильно говорит моя жена, дети у меня красивые, а то что я делаю руками - никуда не годицца. 

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

DetSimen пишет:

чуть протрезвею, и из этой темы все свои сапщения самоликвидирую.  

Как правильно говорит моя жена, дети у меня красивые, а то что я делаю руками - никуда не годицца. 

)))
 

кстати, посмотрел freeRTOS они приоретизацию задач делают, может и с твоими таймерами надо так?

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

Каоче, вот мои последние предположения.  Таймер генерирует прерывания железно, они всегда приходят и всегда выполняются.  Проблема может быть в том, что не успевает вовремя отрабатывать отклик на сапщения в очереди.  Значить, надо попробовать сбрасывать флаги и делать всю нужную фигню не в очереди сообщений, не там где обрабатывается msg_TimerEnd, а перенести это в функции прерываний от таймера, в void tmr...();  

Если и эта не поможет, тада я пас. 

void tmrTXTimer(void) {     // здесь кончился таймер передачи бита/паузы

	TXBusy = false;			// можно передавать следующий

	if (TXState == enumTXState::Bit) { // если передавали бит, передадим 1 паузу
		TXOnOff(false);					// выключим ключ
		TXCurrentMask >>= 1;
		if (TXCurrentMask>0) sendPause(); else sendPause(3); // а если знак кончился, то 3 паузы
	}
	TimerList.Stop(hTXTimer); // остановим этот таймер 
}

void tmrSerialTimer(void) {  // строку приняли до конца
	TXStopped = false;		// можно стартовать передаччик, есличо
	TimerList.Stop(hSerialTimer); // таймер больше не нужен
}

а ветку в switch в loop, где обрабатывается msg_TimerEnd удалить совсем

 

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

и у всех глобальных bool флагов поставить volatile.  Ну и не только у них, а у всего, что меняется в функциях tmr...(). TXState там,  TXCurrentMask и тыды.

Я свой стэнд уже разобрал, поэтому пробовать тебе самаму придёца. 

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

DetSimen пишет:

и у всех глобальных bool флагов поставить volatile.  Ну и не только у них, а у всего, что меняется в функциях tmr...(). TXState там,  TXCurrentMask и тыды.

Я свой стэнд уже разобрал, поэтому пробовать тебе самаму придёца. 

Хорошо! Попробую осмыслить, что ты сказал )))

Green
Онлайн
Зарегистрирован: 01.10.2015

А тут без 100 грамм никак... 
Помнится как то со знакомым ехали на машине, ну и разговаривали ес-но. Когда знакомый вышел, мне водитель спрашивает, слушай, о чём вы всё это время говорили? Я нифига не понял...) При том что он тоже вроде как р/любитель был.)

Это просто вспомнилось, не применительно к данному случаю.)

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

Green пишет:

А тут без 100 грамм никак... 
Помнится как то со знакомым ехали на машине, ну и разговаривали ес-но. Когда знакомый вышел, мне водитель спрашивает, слушай, о чём вы всё это время говорили? Я нифига не понял...) При том что он тоже вроде как р/любитель был.)

Это просто вспомнилось, не применительно к данному случаю.)

100 грамм, тут этим наврядли обойтись

lean_74
Онлайн
Зарегистрирован: 22.12.2015

Дед, только не вздумай ничего удалять, с бочкой удалил, хорошо я частично скопировал... Ну не всем так дано мыслить, а из примеров собрать, кое- то получается.

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

lean_74 пишет:

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

На бочку я ссылку давал, она на Амперке до сих пор валяеца. 

да и туть https://github.com/DetSimen/Useful ее всегда можно скачать

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

Да, удалять нельзя, тем более если опрос датчика скорости делать неправильно, а именно в цикле loop всё работает как часы )))

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

ua6em пишет:

 в цикле loop всё работает как часы )))

это ты просто чота не заметил

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

DetSimen пишет:

ua6em пишет:

 в цикле loop всё работает как часы )))

это ты просто чота не заметил

у меня абсолютный слух, тем более морзянку принимаю в фоновом режиме, обязательно бы услышал

Green
Онлайн
Зарегистрирован: 01.10.2015

Вспоминаю скоростной приём. Там заказываешь 5 скоростей, результат по лучшей принятой. Так вот, на первых скоростях думаешь о чём попало, принимая в фоновом режиме, и только на последующих уже начинаешь напрягаться.)

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

Потестировал этот скетч (вроде как абсолютно идеологически неправильный)
во всех диапазонах скоростей работает как швейцарские часы )))
 

/*
    Name:       Morze.ino
    Created:  21.04.2019 4:16:26
    Author:     DetSimen
*/

//#include <EEPROM.h>
#include "Arduino.h"
#include "MorzeTable.h"
#include "TimerList.h"
#include "Messages.h"

#define toneFreq (800) //частота звука (выбирайте между 600 - 1000Гц)
static uint8_t TXPin = 13;  // пин передаччика
int tonePin = A4;    // выход звука на радиостанцию
int mySpeedPin = A0; // потенциометр скорости
int mySpeed;         // переменная для потенуиометра

extern TTimerList TimerList;  // списой таймеров (до 10) паумолчанью

TMessageList MessageList(12);  // очереть на 12 сапщений

static const int msg_ReadSerial = 0x100;   // сообщение "Читать Сериал"
static const int msg_SendChar = 0x101;    // сообщение "Передать символ (букву)"
static const int msg_SendNextBit = 0x102; // сообщение "Передать следующий бит в букве"
static const int msg_ReadSensors = 0x103; // считать потенциометр скорости

static /*const*/ uint32_t DOT_TIME = 35;  // основное время, длительность точки 75 мс, остальные производные
static /*const*/ uint32_t DASH_TIME = 3 * DOT_TIME; // длительность тире

static const uint16_t REPEAT_TIME = 5000;  // Задержка в мс между повторениями текста, по умолчанию 5 сек. 
static const uint16_t SERIAL_TIMEOUT = 2000; // если в течение 2000 мс не было данных с сериала, значит приняли всю строку

static const uint8_t MAX_STRING_LENGTH = 128; // макс длина передаваемой строки

enum class enumTXState : bool { Pause = false, Bit = true };  

enumTXState TXState = enumTXState::Pause;  // что передаем в данный момент: или бит (точка/тире) или паузу

THandle hTXTimer = INVALID_HANDLE;       // таймер передаччика
THandle hSerialTimer = INVALID_HANDLE;  // таймер таймаута приема из Serial
THandle hRepeatTimer = INVALID_HANDLE;  // таймер повтора фразы
THandle hSensorRead = INVALID_HANDLE;   // таймер для опроса потенциометра скорости передачи

uint8_t TXCurrentMask = 0;   // маска текущего символа
uint8_t TXCurrentCode = 0;   // битовый код Морзе текущего символа
bool  TXBusy = false;   //  идет передача бита или паузы
bool  TXStopped = false;  //  передаччик остановлен нахрен. ничего не передаеца


String StringToTransmit;            // строка, которую будем слать 
uint16_t TransmitCharIndex = 0;   // индекс текущего символа, в этой строке


void TXOnOff(const bool On) {  // передаччик вкл/выкл
  digitalWrite(TXPin, On);
  if(On) {tone(tonePin, toneFreq);}else{ noTone(tonePin);}
}

void tmrTXTimer(void) {     // здесь кончился таймер передачи бита/паузы
  SendMessage(msg_TimerEnd, hTXTimer);
  TimerList.Stop(hTXTimer); // остановим этот таймер 
}

void tmrSerialTimer(void) {  // строку приняли до конца
  SendMessage(msg_TimerEnd, hSerialTimer);
  TimerList.Stop(hSerialTimer); // таймер больше не нужен
}

void tmrRepeat(void) {     // таймер повтора кончился, начинаем передавать сначала
  TransmitCharIndex = 0;
  TXStopped = false;          
  TimerList.Stop(hRepeatTimer);
}

void sendBit(const bool aBit) {  // передать один бит (точку == false или тире == true)

  TXState = enumTXState::Bit;  // признак: передаем бит

  TXOnOff(true);        // ключ на старт!  

  TXBusy = true;        // передаччик теперя занят

  TimerList.setNewInterval(hTXTimer, aBit ? DASH_TIME : DOT_TIME);  // длительность таймера разная для точки и тире
  TimerList.Reset(hTXTimer);  // перезапустим его сначала интервала

}

void sendPause(const uint8_t kf = 1) {  // передаем паузу длиной в 1 точку по умолчанию
  TXState = enumTXState::Pause;
  
  TXBusy = true; // передаччик занят
  
  TimerList.setNewInterval(hTXTimer, kf*DOT_TIME);  // либо длительность паузы кратна точке в kf раз
  TimerList.Reset(hTXTimer);  // перезапустим таймер сначала
}

void tmrSensorRead(void){
  SendMessage(msg_ReadSensor);  // пхаем в очередь сообщение на чтение потанцометра
}

; void setup()
{
  Serial.begin(115200);
  delay(1000); // чтоб всё устаканилось к старту
  pinMode(TXPin, OUTPUT);
  TXOnOff(false); // ключ выключен

  // все таймеры создаюца по умолчанию остановленными
  //
  hTXTimer = TimerList.AddStopped(DOT_TIME, tmrTXTimer);  // таймер передаччика бит 
  hSerialTimer = TimerList.AddStopped(SERIAL_TIMEOUT, tmrSerialTimer);  // таймер таймаута чтения из Serial  
  hRepeatTimer = TimerList.AddStopped(REPEAT_TIME, tmrRepeat);  // таймер повтора передачи строки 
 // hSensorRead = TimerList.Add(tmrSensorRead, 100); // таймер опроса потенциометра скорости опрашиваем раз в 0.1 секунды (на этой строке валится)

  StringToTransmit.reserve(MAX_STRING_LENGTH); // хапнем сразу место под строку, чтоб не перераспределять потом
  StringToTransmit = "CQ DX UA6EM CQ DX UA6EM QSA? 73! 73! 73! K";  // строка для передачи по умолчанию
  TransmitCharIndex = 0;  
}

void loop()
{
  if (Serial.available()) {        // если в сериал чота припрыгало
    SendMessage(msg_ReadSerial);  // пошлем команду прочесть сериал
    TXStopped = true;       // передачу остановим
    TransmitCharIndex = 0;    // и все индексы и маски обнулим, 
    TXCurrentCode = 0;      // так как после приема будем передавать уже новую строку
    TXCurrentMask = 0;
  }
  // тут читаем потенциометр скорости
     mySpeed = map(analogRead(mySpeedPin), 0,1023,0,15);
     DOT_TIME = 100-mySpeed*5;
     DASH_TIME = 3 * DOT_TIME; 

  if ((not TXBusy) and (not TXStopped)) {  // если передаччик не остановлен и не занят передачей бита

    if (TXCurrentMask > 0)  // если маска еще до конца не сдвинулась
    {
      SendMessage(msg_SendNextBit); // передать следующий бит знака
    }
    else 
    {
      SendMessage(msg_SendChar); // знак кончился, начать передавать след. символ
    }
  }


  if ( not MessageList.Available()) return;   // если сапщений в очереди нет, выходим

  TMessage msg = MessageList.GetMessage();

  switch (msg.Message)
  {
    

  case msg_TimerEnd: {
    if (msg.LoParam == hSerialTimer) {  // кончился таймер приёма по сериал
      TXStopped = false;    // можно стартовать передаччик, есличо
      break;
    }
    if (msg.LoParam == hTXTimer) { // кончился таймер передачи бита/паузы
      TXBusy = false;     // можно передавать следующий

      if (TXState == enumTXState::Bit) { // если передавали бит, передадим 1 паузу
        TXOnOff(false);         // выключим ключ
        TXCurrentMask >>= 1;
        if (TXCurrentMask>0) sendPause(); else sendPause(3); // а если знак кончился, то 3 паузы
      }

      break;
    }

    break;
  }

  case msg_SendNextBit: {   // передаем след. бит  (точка/тире) 
    sendBit(TXCurrentCode & TXCurrentMask);
    break;
  }

  case msg_ReadSerial: {   // чтение из сериала
    if (!TimerList.isActive(hSerialTimer)) {  // если таймер таймаута остановлен 
      StringToTransmit = "";          // значить читаем новую строку
      TransmitCharIndex = 0;
    }
    StringToTransmit += char(Serial.read()); // берем символ из сериал и вклеиваем в строку
    TimerList.Reset(hSerialTimer);      // перезапускаем таймер таймаута (помнишь? 2 секунды после ПОСЛЕДНЕГО символа) 
    break;
  }

  case msg_SendChar: {    // послать знак
    if (TransmitCharIndex < StringToTransmit.length()) { // если строка еще не кончиилась
      char c = StringToTransmit[TransmitCharIndex++]; // взять символ 
      if (c != ' ') {  // если не пробел, то
        TXCurrentCode = getMorzeCode(c);        // по нему взять код Морзя  см. MorzeTable.cpp
        TXCurrentMask = getSymbolMask(getMorzeCode(c)); // и маску    см. MorzeTable.cpp
      }
      else sendPause(7);  // пробел между словами - передаем паузу в 7 точек
    }
    else {    // если строка кончилась
      TXStopped = true;     // остановим передачу
      TransmitCharIndex = 0;      // вернем указатель на 0 символ строки
      TimerList.Reset(hRepeatTimer);  // и запустим таймер для REPEAT
    }
    break;
  }
  // тут читаем потенциометр скорости
  
  case msg_ReadSensor:{
  uint8_t newdottime =100 - map(analogRead(mySpeedPin), 0,1023,0,15)*5; // тут все твои чтения и вычисления
  Serial.print("Скорость = ");
  Serial.print( newdottime);
  if (newdottime != DOT_TIME){   // меняем ТОЛЬКО если значения РЕАЛЬНО ИЗМЕНИЛИСЬ
  DOT_TIME = newdottime;    
  DASH_TIME = 3*DOT_TIME;
  }
  break;
}
    Serial.print("Unknown message code: 0x"); Serial.println(msg.Message, HEX);
    break;
  }

}

 

strarbit
Offline
Зарегистрирован: 12.06.2016

Dear Gentlemen, I'm sure you'll like this site https://morsecode.scphillips.com/translator.html

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

strarbit пишет:

Dear Gentlemen, I'm sure you'll like this site https://morsecode.scphillips.com/translator.html

TKS & 88 )))

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

Значить, так.  Найди у себя файл Messages.h.  Унутре него найди функцию DeleteFirst. В этой функции удали 2 строчки в начале 

uint8_t  sreg  = SREG;

cli();

и одну строчку в конце. 

SREG = sreg;

и пропробуй так запустить.  Мне кажеца тут прерывания от таймера пропадають. 

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

DetSimen пишет:

Значить, так.  Найди у себя файл Messages.h.  Унутре него найди функцию DeleteFirst. В этой функции удали 2 строчки в начале 

uint8_t  sreg  = SREG;

cli();

и одну строчку в конце. 

SREG = sreg;

и пропробуй так запустить.  Мне кажеца тут прерывания от таймера пропадають. 

"яйца не подействовали"

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

тогда точно фпамойку. 

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

DetSimen пишет:

тогда точно фпамойку. 

что так сразу... три таймера отрабатывают штатно, спотыкается на 4-ом...
если бы кто-нить из Гуру посмотрел твой код, мне точно не по зубам )))

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

ua6em пишет:

если бы кто-нить из Гуру посмотрел твой код, мне точно не по зубам )))

мне тоже. 

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

мошт, я его скопипастил где...

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

Green пишет:

Нет, для своего позывного нужно же иметь разрешение с соответствующей категорией и пр. А так получается что вместо тебя работает робот и возможна ситуация когда твоих экземпляров класса может быть несколько.) С одинаковыми позывными! Что как то странненько.)

кстати, изобрели новую моду в цифре, ft8 называется, приходишь значит вечерком, после срача на форуме, включаешь рацию в этой моде, идёшь ужинать, потом променад, потом спать, утром дивишься, сколько ТЫ dx радиосвязей провёл за ночь...одним словом прогресс убивает радиолюбительство...

Green
Онлайн
Зарегистрирован: 01.10.2015

Это ж как резиновая. Эх, ушла романтика.(

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

Green пишет:

Это ж как резиновая. Эх, ушла романтика.(

точнее уходит...

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

ua6em пишет:

кстати, изобрели новую моду в цифре, ft8 называется, приходишь значит вечерком, после срача на форуме, включаешь рацию в этой моде, идёшь ужинать, потом променад, потом спать, утром дивишься, сколько ТЫ dx радиосвязей провёл за ночь...одним словом прогресс убивает радиолюбительство...

лучше бы дубля посадил на форуме срачица и жене кивать, а сам с DX-ами живьём за жизнь гутарил. :) 

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

DetSimen пишет:

ua6em пишет:

кстати, изобрели новую моду в цифре, ft8 называется, приходишь значит вечерком, после срача на форуме, включаешь рацию в этой моде, идёшь ужинать, потом променад, потом спать, утром дивишься, сколько ТЫ dx радиосвязей провёл за ночь...одним словом прогресс убивает радиолюбительство...

лучше бы дубля посадил на форуме срачица и жене кивать, а сам с DX-ами живьём за жизнь гутарил. :) 

тут еще после сочинской олимпиады, за три месяца более 20тыщ связей, особо не хоцца, форум как альтернатива )))

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

дед я тут подумал если чтение потенциометра закладываю не по таймеру а в лупе и всё как часы работает, а через таймер твой глючит, может что-то в таймингах по чтению аналоговых портов дело?

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

Мне нада тексты найти, тогда я посмотрю.  Проблема была в чём?  Символы пропускаеть? 

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

DetSimen пишет:

Мне нада тексты найти, тогда я посмотрю.  Проблема была в чём?  Символы пропускаеть? 

да, пропускает символы, но если опрос датчика скорости (потенциометр) переношу в loop,  всё пучком, а если под это дело заводить еще один таймер - идут пропуски, вот и подумалось, что сама процедура чтения аналогового пина причастна