Простой поисковый радио маячок.

Pavel_liev

с LoRa тонами ничего не выйдет, у нее нет такого режима “сигнальной манипуляции” как у Si4432, а если настраивать работать в FSK, никакого преимущества по дальности не будет, чуйка чипа у нее такая же как у предыдущего маячка, дальность у нее достигнута за счет какой-то обработки и спектра, но не за счет чувствительности. LoRa это в первую очередь цифра, и работает она на другую LoRa, забудьте о радейке, они не совместимы, дальность у нее будет лишь LoRa на LoRa.

Shuricus
Pavel_liev:

у нее нет такого режима “сигнальной манипуляции” как у Si4432

А можно подробнее про этот режим?

Pavel_liev

Shuricus Si4432 будучи в режиме FSK имеет настройку передачи данных лог 0/1 с ноги радиомодуля, например SDI, при этом установив ширину канала как узкополосный ЧМ рации, и делая паузы между пачками, под звуковую частоту, получается имитировать звуковой сигнал узкополосной ЧМ радейки. Владимир в маячке этой ветки все это довел до совершенства, но у Si4432 дальность меньше чем у LoRa, а всегда хочется больше 😒

13 days later
MACINTOSH

Привет! Подскажите есть плата Digispark attiny85, могу ли я использовать ее без выпаивания? И какая версия прошивки последняя для attiny85 и si4432. Скачал версию 6.5 она и является последней?

artrue

Добрый день у меня есть много RFM69HW можно их использовать?

Vladimir_N
artrue:

Добрый день у меня есть много RFM69HW можно их использовать?

Только если сами напишете под них прошивку.

artrue
Vladimir_N:

Только если сами напишете под них прошивку.

Уже пишу, только нужно разобраться с функцией вызова по тону 1750Hz. Есть кусок кода 3 писка с разной мощьностью.

#include <SPI.h>
#define ssPin 10       // SS  Chip select pin for reading/writing to the rf69 registers with SPI

///////////////////////////////////////////////////////////////////////////////////
void setup() {
   Serial.begin(9600);             // baud speed for sending to the arduino serial monitor
  Serial.println("Starting up");  // print to the serial monitor
  pinMode(ssPin, OUTPUT);         // define
  pinMode(9, OUTPUT);
  setupSPI();
  writeReg(0x02,0x34);            // Modulation for OOK, Continuous w.o bit synch, OOK, no shaping
  printReg(0x02);

// multiply desired frequency(MHz) by 16384; convert to HEX; split into 3 blocks with 2 char each
// sample: 432.395*16384=7084359[.68]; 7084359 in dec = 6C1947 in hex; split into 3 hex blocks: 0x6C, 0x19, 0x47

  writeReg(0x07,0x6C);  // 6C,19,47 defaults to a frequency of approximately 432.395 MHZ with crystal tolerance ~  MHz
  writeReg(0x08,0x19);  //
  writeReg(0x09,0x47);  //

//  writeReg(0x07,0x6C);  // 6C,19,19 defaults to a frequency of approximately 432.475 MHZ with crystal tolerance ~  MHz
//  writeReg(0x08,0x19);  //
//  writeReg(0x09,0x19);  //

  printReg(0x07);
  printReg(0x08);
  printReg(0x09);
  // writeReg(0x26,0x07); // CLK off to save power by not enableing an external clock signal on a DIO port.
  // printReg(0x26);
  writeReg(0x01,0x0C);  // Set mode to Transmitter TX mode
  printReg(0x01);
}
////////////////////////////////////////////////////////////////////////////////
void loop() {
beacon(1000);
}

//////////////////////////////////////////////////////////////////////////////////
void printReg(byte data) {
  Serial.print("Register ");
  Serial.print(data);
  Serial.print(" = ");
  Serial.println(readReg(data), HEX);
}

//////////////////////////////////////////////////////////////////////////////////
void writeReg(uint8_t addr, uint8_t value) {
  digitalWrite(ssPin,LOW);
  SPI.transfer(addr | 0x80);
  SPI.transfer(value);
  digitalWrite(ssPin, HIGH);
}

/////////////////////////////////////////////////////////////////////////////////
uint8_t readReg(uint8_t addr) {
  digitalWrite(ssPin, LOW);
  SPI.transfer(addr & 0x7F);
  uint8_t regval = SPI.transfer(0);
  digitalWrite(ssPin, HIGH);
  return regval;
}

/////////////////////////////////////////////////////////////////////////////////
void setupSPI() {
  SPI.begin();
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV4);
}

/////////////////////////////////////////////////////////////////////////////////

void beacon(int timer) {
  // Тон с мин мощьностью
  writeReg(0x11,0x50);
  digitalWrite(9, HIGH);
  delay(timer);
  writeReg(0x11,0x00);
  digitalWrite(9, LOW);
  delay(timer);

  //Средняя мощьность
  writeReg(0x11,0x5F);
  digitalWrite(9, HIGH);
  delay((timer)+1000);
  writeReg(0x11,0x00);
  digitalWrite(9, LOW);
  delay(timer);
  // Максимум
  writeReg(0x11,0x5F);
//writeReg(0x13,0x0F);
  writeReg(0x5A,0x5D);
  writeReg(0x5C,0x7C);
  digitalWrite(9, HIGH);
  delay(timer+2000);
  writeReg(0x11,0x00);
  //writeReg(0x13,0x00);
  writeReg(0x5A,0x00);
  writeReg(0x5C,0x00);
  digitalWrite(9, LOW);
  delay(timer);
}
artrue

Павел помогите разобраться, хочу повторить маяк на модулях RFM69HW. Помогите написать код вызова маяка через тон 1750Hz. Какой алгоритм действий? Что добавить вышеуказанный код?

Pavel_liev:

Там главное разобраться с протоколом чтения/записи, ну писать/читать его регистры, а дальше оно не сложно. Эти модули умеют передавать цифровую информацию, чем ниже скорость тем дальше, но настройка скорости отдельная телега, блок передатчика задается в килогерцах, когда блок приема в специальной генеративной кодовой шняге, там на сайте разработчиков есть даже спец. файл екселя, чтобы считать верные значения для реальной скорости, хотя надежнее не заморачиваться, и взять настройки с маяка. Радиомодуль умеет подавать на ногу уровень, когда случилось какое-то прерывание, удобно ставить на прием валидного пакета, но еще быстрее на прием “префикса”, там в каждой передаче есть технический кусок - префикс, если он “ловится”, модуль думает что дальше будет “дата”, при этом это не гарантирует что сама дата будет точно целой, и чем длиннее инфа, тем больше мусора. Но можно ловить голый префикс, вообще без даты, сработка получается четче. К примеру режим пробуждения маяка сделан на приеме префикса “0b10101010”, на частоте обмена 1.75кГц, ну тон радейки 1.75кГц в узкополосном ЧМ как раз дает непрерывный поток “10101010”(для GFSK с шагом 10КГц лог.0 это наличие несущей на частоте “Х”, и лог.1 такое же наличие несущей на частоте “Х+10КГц”), а модуль тупо выбирает первые попавшиеся что пришли “чистыми”, и дает сигнал прерывания на лапу МК, если прерывание настроено только на это событие, то кода как бы больше нет.

Pavel_liev

artrue какие отличия у RFM69HW мне не известно, а у Si4432 согласно мануалу настаивается скорость работы под частоту передачу бод, которая совпадает с тоном 1750Гц радейки, ширина канала под узкополосный ЧМ, радиомодуль “видит” такой вызывной тон, как постоянный сигнал 0xAA, ну чередование лог. 1 и 0, ведь вызов у радейки занимает обе полосы при ЧМ, а для GFSK это полосы 1 и 0 уровней данных.
Радиомодуль с таким сигналом отлично ловит преамбулу данных, но у звука нет стоповых и префикса, из-за чего дальше он выдаст ошибку пакета, но это не важно, по приему преамбулы можно отследить прерывание внутри модуля, что является сигналом к выходу из сна и начала передачи тонов на нужное нам время.
Алгоритм там такой, МК и модуль спят, раз в сработку таймера вачдог, у меня это 8 секунд, МК будит модуль и мониторит эфир на преамбулу, если ее нет, снова все в сон, а радейка для надежного пробуждения тон должна передавать чуть дольше чем таймер пробуждения вачдог.

Конкретно сами настройки для Si4432, ассемблер, пересылка пакетов конфига, читабельно:

;***настройки частоты***
...
;***модуляция передачи***
ldi R16,0x70
ldi R17,0x80	;активация низкой скорости
rcall spi_write	;подпрограмма пересылки по SPI
ldi R16,0x71
ldi R17,0b00010010;fsk,Direct Mode using TX_Data function via the SDI pin
rcall spi_write	;R16-адрес,R17-дата
;ширина канала передачи
ldi R16,0x72
ldi R17,3		;x625Hz=ширина канала
rcall spi_write


;***настройки приема***
ldi R16,0x1c	;фильтр ширины канала
ldi R17,0b11000001	;4.9КГц
rcall spi_write	;R16-адрес,R17-дата
ldi R16,0x20
ldi R17,0xd6
rcall spi_write	;R16-адрес,R17-дата
ldi R16,0x21
ldi R17,0x00
rcall spi_write	;R16-адрес,R17-дата
ldi R16,0x22
ldi R17,0x98
rcall spi_write	;R16-адрес,R17-дата
ldi R16,0x23
ldi R17,0xeb
rcall spi_write	;R16-адрес,R17-дата
ldi R16,0x24
ldi R17,0x00
rcall spi_write	;R16-адрес,R17-дата
ldi R16,0x25
ldi R17,0x9b
rcall spi_write	;R16-адрес,R17-дата
ldi R16,0x2A
ldi R17,0x20
rcall spi_write	;R16-адрес,R17-дата


;преамбула с радейки 1750Гц
ldi R16,0x33
ldi R17,0b00001010;выкл. заголовки
rcall spi_write	;R16-адрес,R17-дата
ldi R16,0x35
ldi R17,0x7A	;длина преамблы
rcall spi_write	;R16-адрес,R17-дата
ldi R16,0x36
ldi R17,0b01010101
rcall spi_write	;R16-адрес,R17-дата
ldi R16,0x37
ldi R17,0b01010101
rcall spi_write	;R16-адрес,R17-дата


;настройки gpio, переключатель антенны, без этого не будет дальности
ldi R16,0x0b
ldi R17,0x12
rcall spi_write	;R16-адрес,R17-дата
ldi R16,0x0c
ldi R17,0x15
rcall spi_write	;R16-адрес,R17-дата


;***откл.прерывания радиомодуля,чтобы не тупил***
ldi R16,0x05
ldi R17,0x00
rcall spi_write	;R16-адрес,R17-дата
ldi R16,0x06
ldi R17,0x00	;преамбула радейки
rcall spi_write	;R16-адрес,R17-дата
ldi R16,0x03
rcall spi_read	;R16-адрес,R17-дата
ldi R16,0x04
rcall spi_read	;R16-адрес,R17-дата


;***вкл.прием, 0x07="4"***(t=5.6мс)
ldi R16,0x07
ldi R17,0x04
rcall spi_write	;R16-адрес,R17-дата


;проверка на преамбуду радейки для пробуждения
;минимальное определение 16мс
;время spi_read-210мкс, spi_write-226мкс
clr R21
c_metr:
inc R21			;+1
cpi R21,60		;время определения, 60 прогонов, 25мс
brlo no_pream	;если не было преамбулы
rjmp off_beacon	;время вышло,спать
no_pream:
;читаем оба статуса
ldi R16,0x03
rcall spi_read	;R16-адрес,R17-дата
ldi R16,0x04
rcall spi_read	;R16-адрес,R17-дата
sbrs R17, 6	;выполнить если бит байта равен нулю
rjmp c_metr	;нет преамбулы,цикл
;код ниже только если пойман тон вызова

Еще момент, регистры 0х71 и 0х72 нужны для ТХ, и в режиме манипуляции пином с МК мощность ТХ получается чуть выше чем при передаче пакета, почему так не знаю, но максималка у Si4432 именно при конфиге на “Direct Mode using TX_Data function via the SDI pin”. Для Si4432 есть здоровенный отличный фирменный мануал на сайте производителя, там описаны регистры и протокол передачи, даже примеры есть.

1 month later
Pavel_liev

Добавил второй GPS модуль в приемник, теперь программка получила возможность считать расстояние по теореме Пифагора, получили расстояние в метрах, а с направлением, стрелочкой на ЖКИ засада, сам GPS толком не определяет стороны света, использовать еще и модуль компаса не хочется.

Vladimir_N
Pavel_liev:

Добавил второй GPS модуль в приемник, теперь программка получила возможность считать расстояние по теореме Пифагора, получили расстояние в метрах, а с направлением, стрелочкой на ЖКИ засада, сам GPS толком не определяет стороны света, использовать еще и модуль компаса не хочется.

Стрелочку сделать можно, но при этом нужно чтобы приемник двигался тогда можно определить стороны света по разности показаний GPS приемника и направление движения всегда совпадало с одной из сторон приемника. Если приемник стоит или крутится на месте, то только дополнительный модуль и лучше не просто компас, а полный набор датчиков чтобы исключить погрешности от наклона корпуса приемника.

Pavel_liev

Смотрел видео работы таких компасов+гиро, точность низкая, до уровня телефона далеко, стрелка гуляет на треть оборота, больше нравится вариант по GPS, более того у него есть своя софтварная строка угла до севера, стоит попробовать, но точность будет зависеть от количества спутников и скорости перемещения.

Vladimir_N

Нужно гиро+аксель+компас+GPS . Тогда будет нормально. Можно даже без компаса гиро+аксель и поправку делать по GPS. Пример, платы гоночных квадратиков у них как правило не используют компас, но ось Z держат с минимальным дрейфом.
Подобная проблема также неплохо решена в головных трекерах для камер (очков, шлема), там используется полный комплект датчиков.

1 month later
Feruz

Всем привет! Я пришел на форум с ютуб видео Pavel_liev. Пытался на ютубе в комментариях отписаться по этому проекту, но ютуб безжалостно блокировал попытки.

У меня есть комментарий по существу вот к этой проблеме:

Pavel_liev:

получили расстояние в метрах, а с направлением, стрелочкой на ЖКИ засада, сам GPS толком не определяет стороны света

Дело в том, что я занимаюсь похожим проектом, в котором я уже решил задачу относительной навигации между двумя географическими координатами. Я использовал формулу гаверсинусов и азимут по локсодромии. Используя вычисления с двойной точностью можно достичь погрешности меньше 1% при расстояниях между точками до 300 км.
Формулы следующие:

    distance = twice_mean_earth_radius *
               asin( sqrt( pow(sin((lat2 - lat1) / 2), 2) +
                           cos(lat2) * cos(lat1) * pow(sin((lon2 - lon1) / 2), 2)));

    heading = atan((lon2 - lon1) /
                    log(tan(pi_div_by_4 + lat2 / 2) / tan(pi_div_by_4 + lat1 / 2)));

Здесь twice_mean_earth_radius = 12742016, pi_div_by_4 = 0.7853981633974483, lat/lon - координаты точек в радианах

Подробнее можно посмотреть в файле /Firmware/CubeIDE/Code/src/lrns.c проекта на гитхабе: github.com/FeruzTopalov/eleph

По поводу определения сторон света. Современные GPS модули определяют COG (курс относительно земли) достаточно быстро и точно, надо лишь сделать несколько шагов в некотором направлении. При этом они определяют курс относительно истинного севера, а не магнитного как это делает любой компас.

Pavel_liev

Feruz спасибо за пост, не знаю что с ютубом, через раз порой отображает комменты.
Задачу определения расстояния между двумя точками решил с помощью Декарта, путем поиска гипотенузы прямоугольного треугольника: разность долготы в квадрате минус разность широты точек в квадрате будет гипотенузой, дальше корень и имеем расстояние.
В списке параметров GPS видел показчик скорости и курса, но еще не тестировал их, и по специфике работы они должны выдать корректные данные только в движении.
От показчика высоты по GPS отказался, большая погрешность, еще испытывал несколько модулей: Neo6m, atgm336h и Quectel L70-R. Выяснилось что чуйка у Neo6m самая плохая, по быстродействию самым резвым при холодном старте вышел atgm336h, и самым экономичным по питанию L70-R, среднее потребление с пассивной антенной 19мА.
Так же все модули хорошо работают без 3.3в стабилизации, на передатчике радиомодуль и GPS запитываются от литиевого АКБ, его напряжение полного заряда 4.2в ничему не навредило.

Pavel_liev

произвел тест курса и скорости, и по показаниям строки $GPVTG с 9’ю спутниками получилось, что курс GPS вменяемо определяет уже с 0.5км/ч, скорость так же отлично мониторится.

Feruz

Интересный подход с Пифагором. Если не ошибаюсь вы пишите на ассемблере, поэтому такое упрощение? Оценивали погрешность такого расчета?
Согласен насчет Neo6m, впечатления от него самые грустные. Все-таки 2009 год выпуска если не ошибаюсь. Я в своем проекте выпаивал стабилизатор с платы Neo6m чтобы напрямую от 3.3В питать.
Сейчас на али можно купить 8е поколение Ublox, с ним достижимо потребление около 10 мА и это при связке GPS+GLONASS. И кстати как упоминалось выше новое поколение умеет и трек писать, и относительное положение рассчитывать до нужных точек, назначать geo fence и много других плюшек.

Pavel_liev

Только ассемблер, только хардкор! 😃
Погрешность математически по Пифагору отсутствует, а так узкое место корень квадратный, использовал код с радиокота, при сверении с гуглокартой отклонений не заметил. Ассемблер хорош для AVR, если делать на STM32 то конечно проще на Си.

Pavel_liev

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

А так для правильного расчета: долгота экватора * cos(широты) = долгота местная. Пример: 1° широты = 111км, долгота на экваторе тоже 111км, но у меня 50°N, cos(50°)=0.64, 111km*0.64=71km, значит 1° местной долготы это 71км.

Геннадий10

Маленький вопрос- какую ATTINY нужно использовать для маяка, ATTINY 13, или можно использовать и ATTINY 13A? Сейчас не вспомню,но у них, есть какая то разница.

Pavel_liev

Как пишут в великом гугле, 13’х тинек без “А” не выпускают уже очень долго, отличия были по питанию и каком-то регистре. Для маячка подходит любая.