Bruk av LoRa-radioer med Micropython

 54 total views,  1 views today

LoRa er en radioteknologi som overfører digitale data med lav hastighet, men som oppnår lang rekkevidde med lav utstrålt effekt. Radioene er billige, men kan kreve noe programmering for å kople dem til en datamaskin. Vi viser noen eksempler på hvordan.

(c) Anders Fongen, mai 2024

Innledning

Fra radioteorien kan vi finne formler som viser den øvre grensen for overføringshastighet av digitale data, og at denne grensen synker ved svakere mottatt signal (dårligere signal/støy forhold), Dersom vi ikke trenger høy overføringshastighet kan vi altså benytte radioer med lav utgangseffekt og lang rekkevidde. Radioer med lav utgangseffekt kan være små og lette, ha liten antenne og lang driftstid på batteriet. Dette er akkurat hva vi trenger i såkalte “Internet-of-Things”-anvendelser, hvor f.eks. batteridrevne sensorer skal overvåke miljøvariabler i et gartneri, eller som skal detektere inntrengere på et sperret område.

Long Range radio

En radiotype som egner seg for dette formålet kalles LoRa, en forkortelse for “Long Range”. Vi snakker ikke om en tradisjonell radio med boks og knapper, men et kretskort som koples opp og kontrolleres av en datamaskin eller mikrokontroller. Under vises bilder av LoRa-radioer i to utgaver:

Modulen til venstre er billigst, men vanskeligst å jobbe med, fordi endekontaktene står veldig tett og er vriene å lodde. Denne modulen har SPI-grensesnsitt, i motsetning til modulen til høyre, som har et seriegrensesnitt. Den til høyre har pinner med 0.1 tommes avstand som passer i vanlige eksperimentbrett (breadboard) og er derfor enklere å jobbe med. Vi har gjort eksperimenter med denne modulen, den lages av EByte og kan levere opptil 1 watt (30 dBm) utgangseffekt.

LoRa-modulen koples til en datamaskin/mikrokontroller for konfigurasjon og datatrafikk. I denne artikkelen har vi benyttet Raspberry Pico. Andre enheter, som Arduino, ESP32 eller Raspberry Pi kan også brukes, men da med nødvendige endringer i konfigurasjonen og programmet. Vi vil referere til denne enheten som mikrokontrolleren.

LoRa-moduler er alle basert på en brikke fra Semtech med betegnelsen SX1276/77/78/79. Disse 4 modellene er realtivt like og adskiller seg i hovedsak med ulike radiofrekvenser. Det er ikke likegyldig hvilke frekvenser du kan bruke! Norske myndigheter (NKOM) har strenge regler for radiosendinger som bør overholdes. Flere opplysninger om dette kommer senere i artikkelen. Her følger noen detaljer:

Selve databladet til Semtech’s LoRa-brikke finnes på denne lenken, Den trenger du ikke lese før du vil gå i dybden på virkemåten.

E32 LoRa-modul fra Ebyte

E32 LoRa-modulen som er brukt i dette eksperimentet er vist til høyre på bildet over. Der fremgår det også hvilke funksjoner som ligger på de ulike pinnene. Disse pinnene brukes på denne måten:

  • M0, M1 – inputsignal (fra mikrokontrolleren til E32) som avgjør om LoRa-modulen skal settes i konfigurasjonsmodus eller dataoverføringsmodus. De koples til to porter på mikrokontrolleren, i vårt tilfelle GPIO18 og GPIO19.
  • RXD, TXD – for å sende og motta data (konfigurasjonsdata eller nyttetrafikk, avhengig av signalene på M0 og M1). De koples “i kryss” til tilsvarende porter på mikrokontrolleren, altså med TXD til RX-porten og RXD til TX-porten.
  • AUX – Et utgående signal fra LoRa-modulen som signaliserer om den kan motta data, eller om den ønsker å overføre data fra mottatte radiosignaler. I vårt eksperiment viste det seg at denne pinnen trenger en ekstern pullup motstand!
  • Vcc og GND – Koples til 3.3 volt spenningsforsyning og jord.

Tilkopling til Raspberry Pico

Pinnene på E32 LoRa-modulen ble koplet til pinner/porter på Raspberry Pico på denne måten.

  • M0 – GPIO18, M1 – GPIO19
  • RXD – TX på UART0, pin 21
  • TXD – RX på UART0, pin 22
  • AUX – GPIO20, med pullup-motstand (1 kOhm) til 3.3v
  • Vcc – 3.3v pin 36
  • GND – GND på pin 38
E32-modulen til høyre koplet til en Raspberry Pico. Pullup-mostanden for AUX-pinnen skimtes mellom ledningene.

Nødvendig programvare

Det finnes programvarebiblioteker i microPython for kontroll av brikken SX1276 (og de andre variantene) med SPI-grensesnitt, men de kan ikke brukes mot EByte’s LoRa-moduler. EByte har plassert sin egen mikrokontroller på modulen med sitt eget grensesnitt for konfigurasjon. Programvare vi kan bruke må altså være tilpasset dette.

Vi fant et bibliotek på GitHub hvor enkeltfiler i Python kan lastes ned og installeres i mikrokontrolleren fra denne lenken. De var til stor hjelp, men krevde også noen endringer for å virke korrekt med de modulene som vi eksperimenterte med. Forklaring følger.

Nødvendige endringer i programvaren

Programvaren fra lenken vist ovenfor virket ikke uten endringer. Vi kan ikke fastslå om det skyldes programmeringsfeil eller endret firmware i E32-modulen. Dersom det siste er tilfelle (noe vi antar) vil det være nødvendig med litt eksperimentering dersom disse endringene ikke gir ønsket resultat.

  • Programkoden for å konfigurere E32-modulen ligger i filen lora_e32.py. I funksjonen get_configuration() vil responsen fra modulen leses i linje 463 og siden analyseres. Vår observasjon er at de ønskede 6 bytes kommer med en ekstra byte foran og bak (med verdien 0), og disse må fjernes før responsen blir analysert.
        data = self.uart.read()

skal derfor erstattes med

        datax = self.uart.read()
        print(datax) # For kontrollformål
        data = datax[1:-1]

  • Funksjonen clear_UART_buffer() på linje 591 vil tømme mottaksbufferen ved å lese dataene som ligger der, inntil det skjer en “timeout”. Dersom det er trafikk på kanalen vil den stadig motta data, og denne funksjonen vil tilsynelatende “henge”. En endret løsning for denne funksjonen er å spørre etter antall bytes i bufferet, for deretter å lese dette antall bytes. Funksjonen foreslås gitt dette innholdet:
    def clean_UART_buffer(self):
        n = self.uart.any()
        self.uart.read(n)
  • I filen set_configuration.py er det en feil i linje 56. Leddet wakeUpTime skal erstattes med wirelessWakeupTime.

Eksempel på enkelt sending og mottak

Med de endringene som er vist ovenfor, og med AUX-linjen koplet til en ekstern pullup-motstand (vi brukte en uke på å finne ut at dette var årsaken til at ingenting funket som forventet), skal det nå ikke mange programlinjene til for å sette opp en forbindelse mellom to E32-moduler. Her er eksempel på sende- og mottaks-modul:

Sending av en tegnstreng (klokkeslett) med faste intervaller:

from lora_e32 import LoRaE32, Configuration
from machine import UART, Pin
import utime
from lora_e32_constants import FixedTransmission, TransmissionPower, AirDataRate
from lora_e32_operation_constant import ResponseStatusCode

# Initialize the LoRaE32 module
uart2 = UART(0, rx=Pin(17), tx=Pin(16))
lora = LoRaE32('433T30D', uart2, aux_pin=20, m0_pin=18, m1_pin=19)

code = lora.begin()
print("Initialization: {}", ResponseStatusCode.get_description(code))

# Set the configuration to default values and print the updated configuration to the console
# Not needed if already configured
configuration_to_set = Configuration('433T20D')
configuration_to_set.CHAN = 27
configuration_to_set.OPTION.fixedTransmission = FixedTransmission.TRANSPARENT_TRANSMISSION
configuration_to_set.OPTION.transmissionPower = TransmissionPower('433T30D').\
                                                    get_transmission_power().POWER_30
configuration_to_set.SPED.airDataRate = AirDataRate.AIR_DATA_RATE_010_24
code, confSetted = lora.set_configuration(configuration_to_set)
print("Set configuration: {}", ResponseStatusCode.get_description(code))

# Send a string message (transparent)
while True:
    message = str(utime.time()) + '\n'
    code = lora.send_transparent_message(message)
    print(message)
    utime.sleep(5)

(her brekker noen kodelinjer, men med copy-paste inn i en teksteditor retter dette seg).

For å motta disse meldingene på en annen radio (som også varsles med et pip, og innholdet vises i et OLED-display), kan denne koden brukes:

from lora_e32 import LoRaE32, Configuration, BROADCAST_ADDRESS
from machine import UART, Pin, I2C
import ssd1306
import utime

from lora_e32_constants import FixedTransmission, AirDataRate
from lora_e32_operation_constant import ResponseStatusCode

# using default address 0x3C
i2c = I2C(1,sda=Pin(14), scl=Pin(15))
display = ssd1306.SSD1306_I2C(128, 64, i2c)
print("I2C ok")

# Initialize the beeper
beep = Pin(2,Pin.OUT)

# Initialize the LoRaE32 module
uart2 = UART(0, rx=Pin(17), tx=Pin(16))
lora = LoRaE32('433T30D', uart2, aux_pin=20, m0_pin=18, m1_pin=19)
print("UART ok")
code = lora.begin()
print("Lora started")
configuration_to_set = Configuration('433T30D')
configuration_to_set.CHAN = 27
configuration_to_set.OPTION.fixedTransmission = FixedTransmission.TRANSPARENT_TRANSMISSION
configuration_to_set.SPED.airDataRate = AirDataRate.AIR_DATA_RATE_010_24
print("Configration ready")
code, confSetted = lora.set_configuration(configuration_to_set)
#print("Set configuration: {}", ResponseStatusCode.get_description(code))

print("Waiting for counter messages...")
while True:
    if lora.available() > 0:
        code, value = lora.receive_message(delimiter=b'\n')
        #print(ResponseStatusCode.get_description(code))
        # Display on OLED display
        display.fill(0)
        display.text(value,5,8)
        display.show()
        # Beep to notify the reception
        beep.on()
        utime.sleep(0.2)
        beep.off()
        print(value) #Print to console also
        #utime.sleep_ms(2000)

Noen av disse programlinjene kan utelates om ønskelig, fordi de kun gir informasjon til konsollet, eller de setter konfigurasjonsverdier som er standard ved oppstart av modulene. Merk også at verdiene som beskriver pin-nummer og gpio-nummer må endres om du ønsker å bruke andre porter på Raspberry Pico, eller om du bruker en annen mikrokontroller, f.eks. ESP32.

Adressering og kringkasting

I et nett av LoRa-moduler vil det være behov for å sende meldinger til enkeltmottakere (Unicast), basert på deres adresser, samt å sende til alle (Broadcast). Også sendinger til enkeltmottakere kan avlyttes av andre, så det er ingen beskyttelse av konfidensialitet i LoRa. Sendinger kan skje på tre måter:

  • Fixed Unicast: Sendingen påføres mottakerens adresse sendes som Unicast
  • Fixed Broadcast: Sendingen påføres en kringkastingsadresse (xFFFF), og sendes som Broadcast
  • Transparent: Sendingen påføres ikke adresse, og sendes som Broadcast

Sender og mottaker må selvfølgelig være konfigurert til samme radiokanal. Maksimal lengde på en melding er 58 bytes i Transparent modus, 55 bytes i Fixed modus.

Forhold mellom sender- og mottakerkonfigurasjon og hvilke kombinasjoner som tillater overføring

Sendingsvarighet og kanalbredde

LoRa har relativt lav overføringshastighet, maksimum 19200 bits/sekund og egner seg ikke til overføring av bilder, video eller lyd. Ved høy hastighet vil rekkevidden være lavere og feilraten høyere. Programeksemplet ovenfor sender meldinger hvert 5 sekund ved 2400 bits/sekund, og ved å studere dette signalet med en SDR-dongle og programmet GQRX (på Linux, på Windows kan SDR# brukes) kan vi fremstille et “fossefall” som viser både kanalbredde (horisontal akse) og sendingsvarighet (vertikal akse). Slik ser filmen ut:

Det er mulig å anslå båndbredden på dette signalet til ca 500 kHz, fra 432,75-433,25 MHz. Det er relativt bredt, og byr på problemer knyttet til lovligheten av å bruke så “brede” signaler. Båndbredden varierer ikke ved forskjellig sendeeffekt og overføringshastighet. Selve LoRa-kretsen kan konfigureres til ulike båndbredder, men det er ikke tilgjengelig på E32-modulen.

Overføringstiden lar seg vanskelig måle på vannfallet ovenfor, men vi lyttet til signalet med en vanlig radio og gjorde lydopptak til programmet Audacity. Dette programmet kan vise et lydsignal (vertikal akse) langs en tidsakse (horisontal akse) og gi oss en pekepinn om når signalet starter og slutter. Slik ser bildet ut på Audacity:

Ved å velge ut det tidsintervallet som sendingen foregår i, vil programmet vise varigheten nederst på skjermen, nemlig 302 millisekunder. Som ventet blir dette intervallet kortere ved høyere overføringshastighet: 63 millisekunder ved 9600 bits/sekund, og 32 millisekunder ved 19200 bits per sekund.

Rekkevidde for meldingsoverføring

LoRa er designet for å gi lang rekkevidde ved lav utstrålt effekt og lav overføringshastighet. I tillegg til disse to parametrene vil antennekonstruksjon og -plassering ha en betydning. Vi satte opp et eksperiment med en LoRa-mottaker i bilen koplet til en antenne på biltaket. Denne antennen er en “pisk” med ca 35 cm lengde.

Antennevalg: Senderen befant seg i huset, koplet til én av to antenner: (1) En kort antenne for håndapparat, plassert i vinduskarmen, eller (2) en 5-elements beam plassert på loftet, pekende ut av loftsvinduet.

Utstrålt effekt: Effekt (tilført antennen) var henholdsvis (a) 21 dBm=125 mW, eller (b) 30 dBm=1 W.

Ved å kjøre rundt i området (Lillehammer) og observere når mottak skjer (programkoden vist ovenfor gir et kort pip ved mottak), danner vi oss et uformelt inntrykk av rekkevidden. Terrenget i området er bebygget og kupert. Resultatene var som følger:

(1)(a) – Stabilt mottak til ca 750 meters avstand, sporadisk mottak utover dette.

(2)(a) – Stabilt mottak til ca 750 meters avstand, men også andre steder med synslinje til huset opp til 3,3 km avstand.

(2)(b) – Stabilt mottak i hele byområdet, langs E6 sydover opptil 10 km avstand. Stedvis mottak med en åskam mellom sender og mottaker (Saksumdalen). Ingen mottak “bak” antennen (en beam-antenne er direktiv og stråler mest i én retning).

LoRa og myndighetenes forskrifter

Bruk av radiosendere er strengt regulert i Norge, og det er på sin plass med noen vurderinger om hvordan LoRa-sendinger kan foregå på lovlig vis. Det er to regelverk som kommer til anvendelse: Fribruksforskriften, som stiller krav til radiosendinger for allmenheten, og Forskrift om radioamatørlisens, som angir krav til radiosendinger for personer med radioamatørlisens (radioamatørlisens tildeles personer som har bestått en såkalt lisensprøve).

La oss først ta for oss vilkårene i Fribruksforskriften, siden den vedkommer alle. Kapittel IV (§11) lister opp en del frekvenser som kan brukes, med oppgitt maksimal utstrålt effekt, båndbredde og sendetid. E32-modulen opererer med 500 kHz kanalbredde, og det er punkt (1), (4) og (5) som tillater dette, men da begrenset til 25 mW utstrålt effekt (14 dBm). Disse frekvensene ligger alle i området 800-900 MHz, som ikke støttes av den E32-modulen som er brukt i dette eksperimentet, men derimot med en annen modell: E32-900T20D. Den opererer i dette frekvensbåndet (862-931 MHz) og med mulighet for å sette utgangseffekten til 14 dBm. Merk at denne utgangseffekten vil gi betydelig kortere rekkevidde, og bruk av antenne med “gain” ikke er tillatt, siden 14 dBm er grensen for utstrålt effekt, ikke effekt tilført antennen.

Med en båndbredde satt til maksimalt 200 kHz kan også punkt (2), (3) og (6) i Fribruksforskriftens §11 brukes, opp til 500 mW (27 dBm). Slik båndbredde er ikke støttet av E32-modulen, så en annen modul basert på SX1276-kretsen må brukes. Spesifikasjonene til SX1276-kretsen oppgis til å kunne operere innenfor denne båndbredden. Rekkevidden og feilraten for en slik konfigurasjon er ikke undersøkt av oss ennå.

Merk at Fribruksforskriften også setter krav til såkalt sendetid, oppgitt i prosent. Denne verdien angir forholdet mellom sendetid og “stilletid”. 1% sendetid betyr at senderen skal være taus i gjennomsnittlig 99% av tiden.

For brukere med radioamatørlisens gjelder §7 i Forskrift om radioamatørlisens, som angir maksimal båndbredde og utstrålt effekt for de ulike frekvensbåndene. Det eneste aktuelle frekvensbånd for LoRa er 432-438 MHz, hvor maksimal kanabåndbredde er 30 kHz. E32-modulen kan ikke operere med 30 kHz båndbredde, men en annen SX-1276 basert modul kan muligens oppnå dette, men dette er ikke undersøkt av oss. Maksimal sendeeffekt for en slik konfigurasjon er hele 300 W, men vi tviler på om det finnes noe ferdiglaget produkt som tilbyr slik utstrålt effekt. Dette blir i så fall noe som må designes og konstrueres av en radioamatør.

Mottak og bruk av ADS-B signaler fra fly

 175 total views

I denne artikkelen beskriver jeg hvordan det er mulig å ta imot radiosignaler fra fly med ADS-B meldinger, og hvilken informasjon disse meldingene inneholder.

(c) Anders Fongen, februar 2024

Fly i normal trafikk sender ut radiosignaler med meldinger om flight-id., posisjon, høyde, fart og retning. Dette skjer i et meldingsformat som kalles ADS-B og er en digital transmisjon på frekvensen 1080 MHz. Dette signalet brukes av luftkontrollen som supplement til radar, og tjenester som Flightradar24 benytter også i stor grad disse radiosignalene.

Kan du ha interesse av å bruke disse signalene? Selv har jeg planer om å bruke fly som reflektorer av radiosignaler, og på den måten utvide rekkevidden av VHF/UHF-signaler over horisonten. Da trenger jeg å vite hvordan antennen skal stilles for å peke mot flyet, og jeg må derfor vite hvor det befinner seg til enhver tid.

Hva du trenger for å motta ADS-B

  • En SDR mottaker av typen RTL-SDR. De finnes på Ebay fra en hundrelapp og oppover. De selges ofte som utstyr for å kunne motta digital TV på PC, men egner seg til mange andre formål også.
  • En Linux-maskin, gjerne en Raspberry Pi. Har du en gammel PC stående som ikke brukes og som har en USB port og nettverksadapter (WLAN eller Ethernet), så bruk gjerne den. Du vil trenge litt Linux-erfaring for å gjennomføre det som blir beskrevet her.
  • Noe gratis programvare som lastes ned fra Internet, bl.a. dump1090.

Oversikt over konfigurasjonen som skal vises her

  1. Radiosignalet fra fly mottas av SDR-dongelen som er koplet til en Linux-maskinens USB-port.
  2. Fra SDR går et “råsignal” (I/Q-signalet) til Linux-maskinen (grønn pil), hvor programmet dump1090 dekoder signalet og henter ut meldingene. Disse meldingene, gjengitt på såkalt SBS-1 format, sendes ut fra Linux-maskinen med TCP-protokoll på port 30003 (rød pil).
  3. Meldingene på SBS-1 format kan leses med et program som man kan skrive selv etter hvilke ønsker man har. Jeg har valgt å lage et Python-program for en Raspberry Pico W mikrokontroller som henter ut flyenes løpende posisjon (lengdegrad, breddegrad, høyde) og regne ut retningen til en direktiv antenne som skal følge flyet.
  4. Raspberry Pico lager elektriske signaler for å styre to motorer på et enkel platform (blå pil) for å stille inn ønsket retning og vinkel (azimuth og elevation).

Konfigurasjon av Raspberry pi (2)

Komponent (2) skal ta imot I/Q-signaler fra SDR-dongelen, dekode ADS-B meldingene som overføres, og presentere data på SBS-1 format gjennom en TCP-forbindelse. For dette trenges en enkel Linux-maskin som må konfigureres for dette formålet. Den følgende beskrivelsen tar utgangspunkt i en Raspberry Pi v.3, men fremgangsmåten blir nokså lik også for andre type Linux. Sørg for at Linux-versjonen er nylig oppdatert.

Følgende kommandoer kan gis for å installere drivere og dump1090-programmet:

$ sudo apt update
$ sudo apt upgrade
$ sudo apt install librtlsdr-dev
$ sudo apt install rtl-sdr
$ git clone https://github.com/antirez/dump1090.git dump1090
$ cd dump1090
$ make

Evt. feilmeldinger følges opp og rettes. På katalogen dump1090 ligger nå programmet dump1090 som startes med kommandoen ./dump1090 --net.

SDR-dongelen kan nå koples til maskinens USB-port og en egnet antenne, slik som vist på figuren. Deretter kan dump1090-programmet startes. Det gir ingen løpende utdata til skjermen, man overvåker utdata på metoden som er vist nedenfor.

Utdata fra dump1090

Som vist på figuren over har vi satt opp dump1090 til å sende ut data i SBS-1 format til TCP-port 30003. Med programmet netcat kan vi ta en titt på hvordan dataene ser ut, og gjøre oss opp en mening om hvordan de kan behandles. Ta en titt på denne videoen:

Det er i hovedsak opplysninger om posisjon og flight-id som er at interesse for denne anvendelsen, men data om retning og fart er også tilgjengelig.

Analyse av SBS-1 data og beregning av antenneretning (3)

Figuren over viser hvordan utdata fra dump1090 overføres via TCP-protokoll til alle som ønsker det (rød pil). Figuren viser derfor at flere ulike anvendelser kan hente disse dataene fra samme dump1090-instans.

I det eksperimentet som beskrives her, skjer denne bearbeidingen i en Raspberry Pico W, som er en mikrokontroller med WLAN-grensesnitt og som kan programmeres i Micropython. Programkoden i denne mikrokontrolleren kan deles i tre deler:

  1. Et hovedprogram som etablerer en TCP-forbindelse til dump1090-noden (2), kaller så på Python-moduler for analyse, beregning og antennestyring
  2. En modul for å analysere SBS-1 melding for posisjon og identifikasjon av fly, og for å beregne antenneretning til flyet.
  3. En modul som mottar opplysninger om antenneretning og styrer servomotorene på antenneplattformen i henhold til disse opplysningene.

1 – Hovedprogram

Hovedprogrammet initialiserer TCP-forbindelsen, WLAN-adapteret, I2C-bussen og oppretter nødvendige objekter for de påfølgende operasjonene. Slik ser programkoden ut:

from wlan_config import wlan_config # WLAN configuration module
from AzElPlatform import AzElPlatform # Az-El antenna control
from AzElCalculator import AzElCalculator
import socket
from machine import Pin, I2C
import ssd1306

# using default address 0x3C
# TODO change GPIO numbers if necessary
i2c = I2C(0,sda=Pin(8), scl=Pin(9))
display = ssd1306.SSD1306_I2C(128, 64, i2c)

# Configure wlan
wlan_config()

# Make network tocket and connect to ads-b listener
sock = socket.socket()

# TODO change IP address to the actual dump1090 node
sock.connect(("192.168.2.11",30003))

# Configure bearing calculator (lat,lon,alt)
# TODO Replace numbers with your own location
azelcalc = AzElCalculator(61.1353,10.4419,253)

# Initialize platform motor control
# TODO change numbers to your own use of GPIO ports
azelplat = AzElPlatform(16,17)

# Start reading ads-b messages
while True:
    message = sock.readline().decode()
    result = azelcalc.analyzeMessage(message)
    if result != None:
        print(result) # For debugging only
        
        # If flightId is present, send to OLED display
        flightId = result['flightid']
        if flightId != None:
            distance = int(result['distance']/1000)
            display.fill(0)
            display.text('%s-%d km'%(flightId,distance),5,8)
        else:
            display.fill(0)
        display.show()
        # Find azimuth and elevation from result
        azimuth = float(result['azimuth'])
        elevation = float(result['elevation'])
        # Point antenna in that direction
        azelplat.setDirection(int(azimuth),int(elevation))

Deler av programkoden styrer et OLED-display for å vise flight-id og avstand til fly som blir fulgt av antennen. Disse kan kommenteres bort om dette er uten interesse.

Modulen wlan_config som importeres her er presentert i en annen blogg-artikkel: WLAN-konfigurasjon i Raspberry Pico W. Der vises hvordan wlan-adapteret kan konfigureres uten å skrive nettverkspassordet inn i koden.

2 – Analyse og behandling av SBS-1 utdata, beregningav retning

Metoden analyzeMessage() i modulen AzElCalculator mottar en SBS-1 melding som parameter og henter ut flight-id og posisjonsdata fra den. Programmet beregner så retningen for en antenne som skal følge dette flyet, i form av horisontal og vertikal vinkel (Azimuth og Elevation). For denne beregningen brukes Python-modulen AltAzRange som kan hentes fra denne adressen. Programkoden for AzElCalculator ser slik ut (merk at noen av linjene er lange og er brukket i flere deler):

# Receive SBS-1 message, find position of aircraft and
# calculate azimuth and elevation for the direction to it
from AltAzRange import AltAzimuthRange
class AzElCalculator:
    def __init__(self,myLatitude,myLongitude,myAltitude):
        AltAzimuthRange.default_observer(myLatitude,myLongitude,myAltitude)
        self.airplane=AltAzimuthRange()
        self.flightId = [(None,None),(None,None),(None,None),(None,None),(None,None)]
        
    def analyzeMessage(self,messageLine):
        elements = messageLine.split(",")
        
        # ES Airborne Position Message
        if (elements[1] == '3'):
            icao = elements[4]
            altitude = elements[11]
            if altitude == '': return None
            latitude = elements[14]
            if latitude == '': return None
            longitude = elements[15]
            if longitude == '': return None
            self.airplane.target(float(latitude),float(longitude),float(altitude)*0.3048)
            # Observe that the position is not returned, only the direction
            result = self.airplane.calculate()
            result['icao'] = icao
            result['flightid'] = self.getFlightId(icao)
            return result
        # ES Identification and Category
        elif (elements[1] == '1'):
            icao = elements[4]
            flightid = elements[10].strip()
            if flightid == '': return None
            self.storeFlightId(icao,flightid)
            return None
        # ES Airborne Velocity Message
        elif (elements[1] == '4'):
            result = dict()
            result['icao'] = elements[4]
            result['groundspeed'] = elements[12]
            result['track'] = elements[13]
            result['flightid'] = self.getFlightId(result['icao'])
            # We can return the "result" object, but choose not to
            # return result # is this data is needed
            return None

    def storeFlightId(self,icao,flightId):
        if self.getFlightId(icao) == None:
            # Add flight id to list
            self.flightId.insert(0,(icao,flightId))
            self.flightId.pop() # Kill the oldest entry
    
    def getFlightId(self,icao):
        for (i,f) in self.flightId:
            if i == icao: return f
        return None

3- Styre en direktiv antenne mot flyet

Oppgaven med programmering av to servomotorer for å styre en antenne i to akser (horisontalt og vertikalt) skjer med modulen AzElPlatform som er presentert i en tidligere blogg-artikkel: Styring av servomotor fra Raspberry Pico og Micropython. For ordens skyld gjengis programkoden er:

# Python class to control a simple Azimuth-Elevation
# platform. It uses two SG90 servo motors for the two
# axes. Since they only rotate 180 degrees, the 180
# degree range of the elevation rotor is used to cover
# the left half (180-359 degrees) of the azimuth

from machine import Pin, PWM
class AzElPlatform:

    def __init__(self,azrotor, elrotor):
        self.azport = PWM(Pin(azrotor))
        self.elport = PWM(Pin(elrotor))

        self.azport.freq(50)
        self.elport.freq(50)

    def setDirection(self,az,el): # Angle in degrees
        # Check parameters: 0-359 and 0-90 allowed
        if not az in range(0,360): return
        if not el in range(0,91): return
        if az>180:
            az = az-180
            el = 180-el # Bend elevation backwards for left half
        # Experimentally established values for
        # Calculation of duty cycles corresponding
        # to rotor angles
        dutyAz = 7800 - az * 6600/180
        dutyEl = el * 7000/180 + 1200

        self.azport.duty_u16(int(dutyAz))
        self.elport.duty_u16(int(dutyEl))
Raspberry Pico W med OLED display viser flight-id NOZ191 med avstand 78 km og følger dette flyet med en direktiv antenne.

Oppsummering

I denne blogg-artikkelen har jeg presentert noen aktiviteter som inkluderer bruk av Software Defined Radio, avansert digital dekoding av radiosignaler fra fly, noe programmering og beregninger på posisjonsdata, og styring av servomotorer for antenner.

Mange av disse emnene vil være av interesse i andre anvendelser enn akkurat den som her er presentert. Bruk gjerne delløsningene i denne artikkelen til dine egne prosjekter, og send meg en melding om resultatene blir interessante.

Morsetrener på en Micro:Bit

 401 total views

Med dette utstyret kan man trene på sending og mottak av morsesignaler sammen med andre. Hver deltaker trenger en Micro:Bit (version 2), og programvaren finner du nederst på siden.

Her demonstrerer jeg hvordan Micro:Bit kan brukes for å sende og motta morse

Med morsealfabetet kan du sende og motta tekst ved å overføre korte og lange pipesignaler. På 1800-tallet kom telegraf-tjenesten i gang i Norge, fra nord til sør ble ledninger trukket som kunne overføre elektrisk strøm for dette formålet. Den gang fantes ikke radio, og heller ikke elektronikk som kunne overføre et talesignal. Profesjonelle operatører som var trent i bruk av morse sørget for at telegrammer ble sendt og mottatt, skrevet ned på papir med vanlige bokstaver og levert til mottakeren med bud.

Etter hver ble radiosenderen oppfunnet, men fortsatt uten muligheter for å overføre tale. Morsesignaler var også her i vanlig bruk mellom skip og til landstasjoner.

Da radioene ble utviklet til også å overføre tale, fortsatte allikevel morsesignaler å være i vanlig bruk. Det viste seg at et system med pipetoner var lettere å oppfatte når det var dårlig radioforbindelse, og man trengte mindre effekt for å få frem meldingene. En radiosender med mindre effekt er lettere og billigere, og egner seg i bærbart utstyr.

Mens profesjonell bruk av morse mellom skip og landstasjoner ble avviklet i år 2000, er det fortsatt mange radioamatører som bruker morse, og det er egne frekvensbånd som brukes til dette formål. Bruk av morse er

  • morsomt, fordi det krever øvelse
  • lett å kombinere med selvbygget radioutstyr
  • effektivt, signalene når over lange avstander med lav effekt og enkle antenner

Morsetrening

Morsealfabetet er lett å være, det finner du mange steder på nettet. Her ser du en slik tabell hvor de korte pipesignalene er vist som prikker, de lange som streker.

Det er grunner til at du ikke anbefales å pugge morse som prikker og streker, fordi det kommer til å hindre deg i å oppfatte signalene som bokstaver og ord når hastigheten øker. Det er mye bra programvare gratis tilgjengelig som trener deg i nettopp dette.

Men det er også viktig å trene morse sammen med andre, hvor dere kan sende til hverandre på skift og lage en faktisk samtale. Slik trening vil lære dere å bruke de vanligste forkortelsene, be om repetisjon av deler av meldingen ved behov osv. Dessuten er det morsommere å lære noe nytt sammen med andre. Om du allerede er radioamatør med tilgang til en radiostasjon kan du øve med virkelige radiosendere, i motsatt fall må du bruke andre overføringsmekanismer, som f.eks.

  • En internet taletjeneste (Messenger, Zoom, Skype m.fl.)
  • Lydsignaler i luft

I begge disse tilfellene ovenfor trenger du en morsenøkkel og en “piper” som avgir et pipesignal når du trykker ned spaken på morsenøkkelen. Som du ser her er en morsenøkkel ganske dyr, men du kan selvsagt lagt din egen fordi det er bare en enkel elektrisk bryter.

Alt i ett med Micro:Bit v2

Micro:Bit er en mikrokontroller som inkluderer en del brytere, sensorer, radio, lamper og lydgivere og koster ca kr.400,- (version 2 kreves for dette formålet). Den kan programmeres og brukes til mange formål, og vi har laget programvare slik at den kan brukes til morsetrening. Programmet er gratis og kan lastes ned fra denne siden via en link lenger ned.

  • Bruker knappene på kretskortet som morsenøkkel
  • Brukere lydgiver og lamper på kretskortet for å vise/spille morsesignaler
  • Bruker den innebygde radioen for at flere deltakere kan sende og motta signaler
  • En “virkelig” morsenøkkel kan koples til kretskortet om ønskelig

Med Micro:Bit v2 og den nødvendige programvaren har en gruppe med deltakere alt de trenger for å sende og motta morsesignaler over radio (men med kort rekkevidde, opp til ca 10 meter).

Innlasting av programvaren

  1. Last ned filen CWtransceiver.hex
  2. Kople MicroBit til PC med en USB-kabel
  3. Nå vil det vises en ny “disk” i FileExplorer, kalt MICROBIT
  4. Kopiere CWtransceiver.hex til denne “disken” (drag and drop i FileExplorer)

For å teste at programvaren er riktig installert, trykk ned Button A (på venstre side av kretskortet. Da skal du høre en pipetone.

Bruksanvisning for morsetreneren

  1. Du kan bruke treneren alene for å øve sending av morsetegn. Da bruker du Button A for å lage pipelyd.
  2. Om flere Micro:Bit-enheter er i nærheten av hverandre, vil signaler som sendes på en enhet spilles av med pipelyder også på de andre enhetene. Der vil også led-lampene på kretskortet lyse opp i samme takt.
  3. Om du berører touch-sensoren (på forsiden av kretskortet like ved USB-kontakten, den har to prikker med en oval rundt), vil LED-displayet skiftevis vise “P” og “S”. Om du vil sende morse slik som vist ovenfor (kalt “Straight Key”) skal det vises en “S” i displayet. Dersom det står en “P” i displayet vil Button A og Button B utgjøre en såkalt paddle keyer. Dette er en mer effektiv måte å sende morsetegn på, men den krever litt øvelse for å beherske. Demonstrasjonsvideoen i starten viser hvordan den kan brukes.
    * Button A gir en serie med prikker mens den holdes nede
    * Button B gir en serie med streker mens den holdes nede
    * Begge knappene nedtrykket gir en serie med skiftevis prikk og strek
    * Mens Button A holdes nede, kan Button B gis et kort trykk. Da vil streken bli sendt ferdig, deretter en prikk før strekene igjen blir sendt. Tilsvarende gjelder i motsatt retning.
  4. Om du ønsker å endre hastigheten på prikker og streker i “P” (paddle keyer) innstillingen gjør du som følger:
    * Hold Button A nede slik at du hører en serie prikker bli sendt.
    * Snu kretskortet på høykant til høyre (slik at Button A er øverst). Da vises en høyrepil i LED-displayet og du hører at hastigheten på prikkene øker. Rett opp kretskortet når hastigheten er passe. Tilsvarende senkes hastigheten om du snur kretskortet til venstre (da vises en venstrepil).

Communication between DMR and a computer network

 320 total views,  1 views today

Anders Fongen, November 2022

Abstract: The integration of a sensor network with services from voice communication, text messaging and Global Positioning System (GPS) creates opportunities for improved situational awareness, better safety for field operators, higher confidence in sensor readings and improved return on equipment investment. Digital Mobile Radio (DMR) has been the choice of communication technology for a series of experiments where these potentials have been investigated. Additional technology components used were mostly inexpensive and open source.

The article was published in the The Sixteenth International Conference on Sensor Technologies and Applications (SENSORCOMM 2022) October 2022, Lisbon Portugal.

Demonstration videos

Below are two demonstration videos from the integration experiment, view these if you are not into reading academic papers:

The first video shows how to integrate a DMR radio into an pub-sub network using the MQTT protocol.

Demonstration video from the integration experiment – pubsub intergation

The second video shows how two MMDVM units can provide routing of IP packets across a DMR radio link.

Demonstration video from the integration experiment – IP routing

Full text of article

Download source code

This link allows you to download the source code in the form of a compressed tar file. Please observe that this is experimental code not meant for production, and:

  • The module gwtest.py is the root module, and the execution starts there
  • You will need to import the module dmr_utils3, paho-mqtt, netifaces, etc.
  • You will need to inspect the source code and modify values for ip-addresses, DMR-ids, UDP port number, MQTT topics etc.
  • You need to configure pi-star so that it connects to the Controller at its IP-address.
  • The code also includes code to route IP-packets over a DMR link. Un-comment this code if necessary, but this will require the program to run in root mode (sudo…)
  • If you make improvements and want to share them with me, you are welcome to contact me. Please accept that I cannot spend much time on advice and support otherwise.

The QYT KT8900 radio with an Allstarlink node

 690 total views,  1 views today

Good news: The QYT KT-8900 and KT-8900D radios are well suited for running an Allstalink node. The configuration menu REP-M (#43 on KT-8900, #51 on KT-8900D) allows two radios to make a repeater by connecting a cable between the two microphone connectors (RJ45 plugs). The configuration feeds a RPT-CTLR signal when the squelch opens (or subtone received) through the mic connector which is wired to the PTT on the other radio.


The RPT-CTLR is effectively a COR signal which can be wired to the DMK URI for Allstarlink operation, and no modification to the radio circuit board is necessary. As a proof of concept, I sacrificed an ethernet cable and soldered a DB25 plug on it according to the wiring shown on the picture. This works as expected and with good sound quality. The KT-8900D offers much radio for the money, and I believe it should be interesting for use in private Allstarlink nodes.
The RPT-CTLR is active low, so you need to set “carrierfrom=usbinvert” in simpleusb.conf


After 3 hours operation on 95% duty cycle, the radio is only lukewarm, using low output power (10w)

The Allstalink node connected to the Mic connector of KT8900D

The wiring arrangement for the DB25 and the DMK URI board