sunnuntai, 17. kesäkuu 2018

Decoding pulse-width modulation with GNU Radio and Audacity

grc-pic.jpg
https://ibb.co/nxgjcy

aud-pic1.jpg

https://ibb.co/f53ajd

Effect -> Amplify...
aud-pic2.jpg

aud-pic3.jpg
Short and long width pulses (1's 0's ...)  https://ibb.co/b52Ajd

Measuring pulse width
aud-pic4.jpg
https://ibb.co/h2q2xy

torstai, 14. kesäkuu 2018

Decoding 2-FSK with GNU Radio

RX: RTL-SDR.COM V.3, GNU Radio, Python
TX: Arduino Uno & Dragino Lora Shield (Semtech SX1278) http://wiki.dragino.com/index.php?title=Lora_Shield
436 MHz 1200 bps 2-FSK
NRZ, CRC OFF, preamble polarity 0xAA, preamble length 24, no sync words

Arduino code (Open-Electronics sx1278 library is available in GitHub. https://github.com/open-electronics/LoRa/releases)
SX1278 datasheet: https://cdn-shop.adafruit.com/product-files/3179/sx1276_77_78_79.pdf

#include <SX1278.h>

#define SERIAL_SPEED        9600
#define FREQ                436
#define BPS                 1200
#define STATE_STANDBY       1
#define STATE_FSTX          2
#define STATE_TX            3
#define S_DELAY             1
#define L_DELAY             10
#define ST_DELAY            550
#define TX_DELAY            1000
#define NUM_SYNC_BYTES      3
#define TX_BUFFER_LEN       34
#define SX_BEGIN            "SX.begin"
#define SX_BITRATE          "SX.readBPS "
#define SX_FREQ             "SX.readFreq "

#define RegRxBw             0x12
#define RegOokPeak          0x14
#define RegPreambleMsb      0x25
#define RegPreambleLsb      0x26
#define RegSyncConfig       0x27
#define RegPacketConfig1    0x30
#define RegPacketConfig2    0x31

byte syncBytes[NUM_SYNC_BYTES] = {0x01, 0x01, 0x01};
byte txBuffer[TX_BUFFER_LEN] = {65,65,65,65,65,65,66,66,66,66,66,66,70,70,70,70,70,70,48,48,48,48,48,48,32,32,32,32,32,32,10,10,10,10};

void setup() {
  Serial.begin(SERIAL_SPEED);
  if (SX.begin()) {
    Serial.println(F(SX_BEGIN));
    delay(S_DELAY);
    SX.startModeFSKOOK();
    SX.setModulation(0); // FSK

// Channel filter bandwidth control. RxBwMant (bits 4-3): 01->20 & RxBwExp (bits 2-0): 4 = 25 kHz  
    byte b = SX.SPIread(RegRxBw);
    bitClear(b, 4);
    bitSet(b, 3);
    bitSet(b, 2);
    bitClear(b, 1);
    bitClear(b, 0);
    SX.SPIwrite(RegRxBw, b);

    SX.setFreq(FREQ);
    Serial.print(F(SX_FREQ));
    Serial.println(SX.readFreq(), DEC);
    SX.setBPS(BPS);
    Serial.print(F(SX_BITRATE));
    Serial.println(SX.readBPS(), DEC);

    // Bits 7-6: AutoRestartRxMode, 01 -> On, without waiting for the PLL to re-lock
    // Bit 4: Enables the Sync word generation and detection: 0 -> Off, 1 -> On
    // Bit 5: Sets the polarity of the Preamble. 0 -> 0xAA, 1 -> 0x55
    // Bits 2-0: Size of the Sync word (SyncSize + 1)
    b = SX.SPIread(RegSyncConfig);
    bitClear(b, 7);
    bitSet(b, 6);
    bitClear(b, 4);
    bitClear(b, 5);
    bitClear(b, 2);
    bitClear(b, 1);
    bitClear(b, 0);
    SX.SPIwrite(RegSyncConfig, b);

    // Bits 6-5: Defines DC-free encoding/decoding performed:
    // 00 -> none, 01 -> manchester, 10 -> whitening
    // Bit 7: packet format, 0 -> fixed length, 1 -> variable length
    // Bit 4: crc calc/check, 0 -> off, 1 -> on
    // Bits 2-1: Defines address based filtering in Rx: 00 -> None (Off)
    // Bit 3: Defines the behavior of the packet handler when CRC check fails:
    // 0 -> Clear FIFO and restart new packet reception. No PayloadReady interrupt issued.
    // 1 -> Do not clear FIFO. PayloadReady interrupt issued.
    // Bit 0: Selects the CRC and whitening algorithms:
    // 0 -> CCITT CRC implementation with standard whitening
    // 1 -> IBM CRC implementation with alternate whitening
    b = 0;
    SX.SPIwrite(RegPacketConfig1, b);

    SX.SPIwrite(RegPreambleMsb, 0);
    SX.SPIwrite(RegPreambleLsb, 24);
    
    b = SX.SPIread(RegPacketConfig2);
    bitSet(b, 6);
    SX.SPIwrite(RegPacketConfig2, b);

    // Bit 5: enables the Bit Synchronizer:
    // 0 -> bit sync disabled (not possible in packet mode), 1 -> bit sync enabled
    b = SX.SPIread(RegOokPeak);
    bitSet(b, 5);
    SX.SPIwrite(RegOokPeak, b);
    
    SX.setPower(2);       // 10 mW

    SX.setState(STATE_STANDBY);
//    SX.setState(STATE_FSTX);
//    delay(S_DELAY);
//    SX.setState(STATE_TX);
    delay(L_DELAY);
  }
}

void loop() {
    SX.dataToSend(txBuffer, TX_BUFFER_LEN);
    delay(L_DELAY);
    SX.setState(STATE_FSTX);
    delay(S_DELAY);
    SX.setState(STATE_TX);
    delay(ST_DELAY);
    SX.setState(STATE_STANDBY);
    delay(TX_DELAY);
}
ardradio.jpg

gnu-fsk.jpg
Full size image https://ibb.co/jEwfUd

32-bit IEEE float IQ file.
Skip head and head blocks are used to decrease durations of noise in the signal. IQ data is recorded with SDRSharp + RTL-SDR (Correct IQ to remove DC spike). Squelch block could be used to eliminate noise before and after FSK data burst. Center_freq value is -200 for adjusting more optimally to the center of the signal. Dev_lo = center_freq - dev. Dev_hi = center_freq + dev.
Samp_per_sym = samp_rate / 1200 / decimation. Omega = samp_per_sym*(1+0.0).
Frequency Xlating FIR filter taps = firdes.low_pass(1.0, samp_rate, (dev_hi - dev_lo), 200).

Python code converts binary file out.txt to text file out-d1.txt

f = open("out.txt", "rb")
d = f.readlines()
f.close()

d[0] = d[0].replace('\x00', '0')
d[0] = d[0].replace('\x01', '1')

f = open("out-d1.txt", "w")
f.write(d[0])
f.close()

print 'converted'

notp-edit.jpg

https://ibb.co/edifCy

byte txBuffer[TX_BUFFER_LEN] = {65,65,65,65,65,65,66,66,66,66,66,66,70,70,70,70,70,70,48,48,48,48,48,48,32,32,32,32,32,32,10,10,10,10};

sunnuntai, 27. toukokuu 2018

Kameratolppa: 590 nm suodin

Sony Cyber-shot DSC-H9. Tolpassa ei kameraa.

Night-shot on.
nvon590-2.jpgnvon590-1.jpg

Night-shot on-off kytkin puoliväli asetuksella.
nvhalf590-1.jpgnvhalf590-2.jpg

Night-shot off.
nvoff590.jpg

lauantai, 26. toukokuu 2018

Investigating OOK signal with Python

Signal source: 433 MHz ISM band, AM demodulated wave file

af1.jpg
https://ibb.co/eYXPY8

Part of the signal zoomed with Pyplot zoom tool
af1zoom.jpg
https://ibb.co/cBQ6fo

from scipy.io import wavfile
from matplotlib import pyplot as plt
import numpy as np

x_offset_lo = 0.348
x_offset_hi = 0.82
y_offset_lo = 140
y_offset_hi = 200
y_lim = 150
y_val = 176

def printWaveInfo():
    print 'Len ' + str(data.shape[0])
    print 'Channels ' + str(data.shape[1])
    print 'Datatype ' + str(data.dtype)
    print 'Samplerate ' + str(sampleRate)

def setYvalues():
    x = 0
    while x < len(data):
        if data[x, 0] > y_lim:
            data[x, 0] = y_val
        x += 1
    
sampleRate, dataVal = wavfile.read('af433-926.wav')
data = np.copy(dataVal)

printWaveInfo()
setYvalues()

times = np.arange(len(data))/float(sampleRate)

plt.figure(figsize=(19, 10))
plt.suptitle('433.926 MHz')
plt.subplot(311)
plt.style.use('seaborn')
plt.xlim(times[0] + x_offset_lo, times[-1] - x_offset_hi)
plt.ylim(y_offset_lo, y_offset_hi)
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.grid(True)
plt.plot(times, data[:,0], color = 'k')

plt.subplot(312)
plt.style.use('seaborn')
plt.xlim(times[0] + x_offset_lo, times[-1] - x_offset_hi)
plt.ylim(y_offset_lo, y_offset_hi)
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.grid(True)
plt.plot(times, dataVal[:,0], color = 'b')

plt.subplot(313)
plt.style.use('seaborn')
plt.xlim(times[0], times[-1])
plt.xlabel('Time (s)')
plt.ylabel('Amplitude')
plt.grid(True)
plt.plot(times, dataVal[:,0], color = 'y')

plt.show()

 

maanantai, 21. toukokuu 2018

Kameratolppa: ZWB1 suodin

Sony Cyber-shot DSC-H9. Tolpassa ei kameraa.

ZWB1 340nm UV pass suodin.
zwb1.jpg

Night-shot on.
nv-on5.jpgnv-on3.jpgnv-on2.jpgnv-on1.jpgnv-on4.jpg

Night-shot on-off kytkin puoliväli asetuksella.
nv-half5.jpgnv-half4.jpgnv-half2.jpgnv-half3.jpgnv-half1.jpg

Sony Cyber-shot DSC-H9. Tolpassa valekamera. ZWB1 340nm UV pass suodin.
valekamera-nv-half1.jpgvalekamera-nv-half2.jpgvalekamera-nv-on1.jpgvalekamera-nv-on2.jpg