Esempio n. 1
0
def main():

    now = datetime.datetime.now()

    current_time = now.strftime("%H:%M:%S.%f")
    print("Current Time =", current_time)
    #aquire location

    #start calibration process (needed?)

    #start syc process

    sdr = RtlSdr()  # rtl-sdr instance
    # configure device
    timeToSample = 1  # in sec
    sampleRate = 2.4e6  # in Mhz
    sdr.sample_rate = sampleRate
    sdr.center_freq = 433e6  # in Mhz
    sdr.gain = 30  # in dB
    print("gain set to:", sdr.get_gain())
    print(now)

    numberOfSamples = sampleRate * timeToSample
    fig = figure()
    ax = fig.add_subplot(111, projection='3d')  # used for 3d IQ/time plot
    samples = sdr.read_samples(numberOfSamples)  # aquire samples
    sdr.close()
    # I/Q seperation
    real = samples.real
    imag = samples.imag
    samp = np.arange(0, numberOfSamples, 1)  # used as an axis
    #ax.scatter(samp[0:-1:100],real[0:-1:100],imag[0:-1:100],marker='^',s=2)#used for pumba slack

    simulateRecivers(real, sampleRate)  # used to simulation
    #plt.subplot(3, 1, 2)
    # xlabel('Real axis')#used for pumba slack
    # ylabel('img axis')#used for pumba slack
    '''
    pxx,farr=psd(samples, NFFT=1024, Fs=sampleRate / 1e6, Fc=sdr.center_freq / 1e6)
    plt.subplot(2, 1, 1)
    plt.plot(samp, imag)
    plt.subplot(2, 1, 2)
    plt.plot(farr,pxx)
    '''
    show()
Esempio n. 2
0
class Input(DataSource.DataSource):
    def __init__(self, source: str, data_type: str, sample_rate: float,
                 centre_frequency: float, input_bw: float):
        """
        The rtlsdr input source

        :param source: The device number, normally zero
        :param data_type: The data type the rtlsdr is providing, we will convert this
        :param sample_rate: The sample rate we will set the source to, note true sps is set from the device
        :param centre_frequency: The centre frequency the source will be set to
        :param input_bw: The filtering of the input, may not be configurable
        """
        # Driver converts to floating point for us, underlying is 8o?
        self._constant_data_type = "16tle"
        super().__init__(source, self._constant_data_type, sample_rate,
                         centre_frequency, input_bw)
        self._connected = False
        self._sdr = None
        self._tuner_type = 0
        self._device_index = 0
        self._gain_modes = ["auto", "manual"]  # would ask, but can't
        super().set_gain_mode(self._gain_modes[0])
        super().set_help(help_string)
        super().set_web_help(web_help_string)

    def open(self) -> bool:
        global import_error_msg
        if import_error_msg != "":
            msgs = f"No {module_type} support available, ", import_error_msg
            self._error = msgs
            logger.error(msgs)
            raise ValueError(msgs)

        if self._source == "?":
            self._error = self.find_devices()
            return False

        try:
            self._device_index = int(self._source)
        except ValueError as err:
            msgs = f"port number from {self._source}, {err}"
            self._error = str(err)
            logger.error(msgs)
            raise ValueError(err)

        try:
            self._sdr = RtlSdr(device_index=self._device_index)
        except Exception as err:
            self._error = f"Failed to connect {str(err)}"
            logger.error(self._error)
            raise ValueError(self._error)

        self._tuner_type = self._sdr.get_tuner_type()

        logger.debug(f"Connected to {module_type}")

        try:
            self.set_sample_rate_sps(self._sample_rate_sps)
            self.set_centre_frequency_hz(self._centre_frequency_hz)
            # self._sdr.freq_correction = 0 # ppm
            self.set_gain_mode('auto')
            self.set_gain(0)
        except ValueError:
            pass
        except Exception as err:
            self._error = str(err)
            raise ValueError(err)

        # recover the true values from the device
        self._sample_rate_sps = float(self._sdr.get_sample_rate())
        self._centre_frequency_hz = float(self._sdr.get_center_freq())
        logger.debug(
            f"{allowed_tuner_types[self._tuner_type]} {self._centre_frequency_hz / 1e6:.6}MHz @ "
            f"{self._sample_rate_sps:.3f}sps")
        self._connected = True

        return self._connected

    def close(self) -> None:
        if self._sdr:
            self._sdr.close()
            self._sdr = None
        self._connected = False

    @staticmethod
    def find_devices() -> str:
        devices = ""
        # could do with a call that returns the valid device_index's
        max_device = 10
        for device in range(max_device):
            try:
                sdr = RtlSdr(device_index=device)
                type_of_tuner = sdr.get_tuner_type()
                # index = sdr.get_device_index_by_serial('0000001')  # permissions required
                # addresses = sdr.get_device_serial_addresses() # permissions required
                sdr.close()
                devices += f"device {device}, type {type_of_tuner} {allowed_tuner_types[type_of_tuner]}\n"
            except Exception:
                pass
        if devices == "":
            devices = f"No rtlsdr devices found, scanned 0 to {max_device-1}"
        print(devices)
        return devices

    def get_sample_rate_sps(self) -> float:
        if self._sdr:
            self._sample_rate_sps = float(self._sdr.get_sample_rate())
        return self._sample_rate_sps

    def get_centre_frequency_hz(self) -> float:
        if self._sdr:
            if self._hw_ppm_compensation:
                self._centre_frequency_hz = float(self._sdr.get_center_freq())
        return self._centre_frequency_hz

    def set_sample_type(self, data_type: str) -> None:
        # we can't set a different sample type on this source
        super().set_sample_type(self._constant_data_type)

    def set_sample_rate_sps(self, sample_rate: float) -> None:
        # rtlsdr has limits on allowed sample rates
        # from librtlsdr.c data_source.get_bytes_per_sample()
        # 	/* check if the rate is supported by the resampler */
        # 	if ((samp_rate <= 225000) || (samp_rate > 3200000) ||
        # 	   ((samp_rate > 300000) && (samp_rate <= 900000))) {
        # 		fprintf(stderr, "Invalid sample rate: %u Hz\n", samp_rate);
        # 		return -EINVAL;
        # 	}
        # logger.info(f"set sr rtlsdr tuner type {self._tuner_type}, {allowed_tuner_types[self._tuner_type]}")

        if (sample_rate <= 225000) or (sample_rate > 3200000) or (
            (sample_rate > 300000) and (sample_rate <= 900000)):
            err = f"{module_type} invalid sample rate, {sample_rate}sps, 225000-3000000 and not 300000-900000"
            self._error = err
            logger.error(err)
            sample_rate = 1e6  # something safe

        self._sample_rate_sps = sample_rate
        if self._sdr:
            try:
                self._sdr.sample_rate = sample_rate
                self._sample_rate_sps = float(self._sdr.get_sample_rate())
            except Exception as err:
                self._error = str(err)
                logger.debug(
                    f"bad sr {sample_rate} now {self._sample_rate_sps}")

        logger.info(f"Set sample rate {sample_rate}sps")

    def set_centre_frequency_hz(self, frequency: float) -> None:
        # limits depend on tuner type: from https://wiki.radioreference.com/index.php/RTL-SDR
        # Tuner 	             Frequency Range
        # =======================================
        # Elonics E4000 	     52 – 1100 MHz / 1250 - 2200 MHz
        # Rafael Micro R820T(2)  24 – 1766 MHz
        # Fitipower FC0013 	     22 – 1100 MHz
        # Fitipower FC0012 	     22 - 948.6 MHz
        # FCI FC2580 	         146 – 308 MHz / 438 – 924 MHz

        freq_ok = True
        ok = True
        # logger.info(f"set cf rtlsdr tuner type {self._tuner_type}, {allowed_tuner_types[self._tuner_type]}")

        # what type of tuner do we have ?
        freq_range = ""
        if self._tuner_type == 1:
            # E4000
            if (frequency < 52e6) or (frequency > 2200e6):
                freq_ok = False
                freq_range = "52 – 1100 MHz and 1250 - 2200 MHz"
            elif (frequency > 1100e6) and (frequency < 1250e6):
                freq_ok = False
                freq_range = "52 – 1100 MHz and 1250 - 2200 MHz"
        elif self._tuner_type == 2:
            # FC0012
            if (frequency < 22e6) or (frequency > 948.6e6):
                freq_ok = False
                freq_range = "22 - 948.6 MHz"
        elif self._tuner_type == 3:
            # FC0013
            if (frequency < 22e6) or (frequency > 1100e6):
                freq_ok = False
                freq_range = "22 – 1100 MHz"
        elif self._tuner_type == 4:
            # FC2580
            if (frequency < 146e6) or (frequency > 924e6):
                freq_ok = False
                freq_range = "146 – 308 MHz and 438 – 924 MHz"
            elif (frequency > 308e6) and (frequency < 438e6):
                freq_ok = False
                freq_range = "146 – 308 MHz and 438 – 924 MHz"
        elif self._tuner_type == 5 or self._tuner_type == 6:
            # R820T or R828D
            if (frequency < 24e6) or (frequency > 1.766e9):
                freq_ok = False
                freq_range = "24 – 1766 MHz"
        else:
            self._error = f"Unknown tuner type {self._tuner_type}, frequency range checking impossible"
            logger.error(self._error)
            ok = False

        if not freq_ok:
            self._error = f"{allowed_tuner_types[self._tuner_type]} invalid frequency {frequency}Hz, " \
                          f"outside range {freq_range}"
            logger.error(self._error)
            ok = False

        if self._sdr and ok:
            try:
                if self._hw_ppm_compensation:
                    self._sdr.center_freq = frequency
                    self._centre_frequency_hz = float(
                        self._sdr.get_center_freq())
                else:
                    self._centre_frequency_hz = frequency
                    self._sdr.center_freq = self.get_ppm_corrected(frequency)
                    # print(f"freq {frequency} ppm {self._ppm} -> {frequency + (self._ppm * frequency / 1e6)}")
                logger.info(f"Set frequency {frequency / 1e6:0.6f}MHz")
            except Exception as err:
                self._error = str(err)

    def set_ppm(self, ppm: float) -> None:
        """
        +ve reduces tuned frequency
        -ve increases the tuned frequency

        :param ppm: Parts per million error,
        :return:
        """
        self._ppm = ppm
        self.set_centre_frequency_hz(self._centre_frequency_hz)

    def get_gain(self) -> float:
        if self._sdr:
            self._gain = self._sdr.get_gain()
        return self._gain

    def set_gain(self, gain: float) -> None:
        self._gain = gain
        if self._sdr:
            try:
                # horrible _sdr.set_gain() - either a number or string
                if self._gain_mode == 'auto':
                    self._sdr.set_gain('auto')
                else:
                    self._sdr.set_gain(float(gain))
            except Exception as err:
                self._error = f"failed to set gain of '{gain}', {err}"

    def set_gain_mode(self, mode: str) -> None:
        if mode in self._gain_modes:
            self._gain_mode = mode
            if self._sdr:
                # because the 'best' way to set the mode is to set the gain, apparently
                self.set_gain(self._gain)
        return

    def set_bandwidth_hz(self, bw: float) -> None:
        if self._sdr:
            try:
                self._sdr.set_bandwidth(int(bw))
            except Exception as err:
                self._error += str(err)
            self._bandwidth_hz = self._sdr.get_bandwidth()

    def get_bandwidth_hz(self) -> float:
        if self._sdr:
            self._bandwidth_hz = self._sdr.get_bandwidth()
        return self._bandwidth_hz

    def read_cplx_samples(self, number_samples: int) -> Tuple[np.array, float]:
        """
        Get complex float samples from the device

        Note that we don't use unpack() for this device

        :return: A tuple of a numpy array of complex samples and time in nsec
        """
        complex_data = None
        rx_time = 0

        if self._sdr and self._connected:
            try:
                complex_data = self._sdr.read_samples(
                    number_samples)  # will return np.complex128
                rx_time = self.get_time_ns()
                complex_data = np.array(
                    complex_data, dtype=np.complex64
                )  # (?) we need all values to be 32bit floats
            except Exception as err:
                self._connected = False
                self._error = str(err)
                logger.error(self._error)
                raise ValueError(err)

        return complex_data, rx_time
Esempio n. 3
0
class Sdr():
    def __init__(self):
        #Abro el dongle
        self.dispositivo = RtlSdr()

        #Lo configuro
        self.dispositivo.sample_rate = 2.048e6  #Hz
        self.dispositivo.center_freq = 1e9  #Hz
        self.dispositivo.freq_correction = 60  #ppm
        self.dispositivo.gain = 49.6  #dB
        self.dispositivo.set_agc_mode(False)

        self.frecuencia_oscilador_local_lnb = 10.5e9

        self.limite_inferior_Ku = 11.45e9
        self.limite_superior_Ku = 12.25e9

        self.nfft = 1024
        self.n = 256

        self.Vref = 1  #V
        self.Zo = 2e3  #Ohm

        self.potencia_calibrada = None

    def leer_potencia(self):
        #Leo las muestras
        iq = self.dispositivo.read_samples(self.n * self.nfft)
        #Calculo la potencia de la señal
        potencia = calcular_potencia(iq, self.Vref,
                                     self.Zo) - self.dispositivo.gain

        return potencia

    def leer_potencia_calibrada(self):
        if self.esta_calibrado() == True:
            return self.leer_potencia() - self.potencia_calibrada
        else:
            return None

    def calibrar(self):
        print('Calibrando...')
        potencia_aux = 0
        for i in range(10):
            potencia_aux += self.leer_potencia()

        self.potencia_calibrada = potencia_aux / (i + 1)
        print('Calibrado a {:2.2f} dBFS'.format(self.potencia_calibrada))

    def esta_calibrado(self):
        return self.potencia_calibrada != None

    def configurar(self):
        entrada = 0
        while entrada != 6:

            entrada = interfaz.imprimir_menu_configuracion()

            if entrada == 1:
                frecuencia = float(
                    input(
                        'Ingrese una frecuencia entre {:f} Hz y {:f} (en Hz): '
                        .format(self.limite_inferior_Ku,
                                self.limite_superior_Ku)))
                if (frecuencia < self.limite_inferior_Ku) or (
                        frecuencia > self.limite_superior_Ku):
                    print('Valor fuera de rango')
                else:
                    self.dispositivo.set_center_freq(
                        frecuencia - self.frecuencia_oscilador_local_lnb)

            elif entrada == 2:
                ancho_banda = float(
                    input(
                        'Ingrese un ancho de banda entre 1 MHz y 3.2 MHz (En Hz): '
                    ))

                if (ancho_banda < 1e6) or (ancho_banda > 3.2e6):
                    print('Valor fuera de rango')
                else:
                    self.dispositivo.set_sample_rate(ancho_banda)

            elif entrada == 3:
                lista = np.array(self.dispositivo.valid_gains_db)

                try:
                    self.dispositivo.set_gain(
                        float(
                            input(
                                'Ingrese una ganancia entre {:2.1f} dB y {:2.1f} dB: '
                                .format(np.min(lista), np.max(lista)))))
                    print('Ganancia configurada en {:2.1f} dB'.format(
                        self.dispositivo.get_gain()))
                except:
                    print('Valor fuera de rango')

            elif entrada == 4:
                try:
                    self.n = int(
                        input(
                            'Ingrese la cantidad de paquetes de 1024 muestras: '
                        ))
                except:
                    print('Valor fuera de rango')

            elif entrada == 5:
                frecuencia_central = self.get_frecuencia_central()  #Hz
                ancho_banda = self.dispositivo.get_sample_rate()  #Hz
                ganancia = self.dispositivo.get_gain()  #dB
                paquetes = self.n
                tamanio_paquete = self.nfft

                print('Configuracion actual: ')
                print('Frecuencia central: {:f} Hz'.format(frecuencia_central))
                print('Ancho de banda: {:f} Hz'.format(ancho_banda))
                print('Ganancia: {:2.1f} dB'.format(ganancia))
                print('Mediciones compuestas por {} paquetes de {} muestras'.
                      format(paquetes, tamanio_paquete))
                print('Tiempo aproximado por medicion: {:f} ms'.format(
                    1e3 * paquetes * tamanio_paquete / ancho_banda))

            elif entrada == 6:
                print('Configuracion realizada\n')

            else:
                interfaz.orden_no_valida()

    def get_frecuencia_central(self):
        return self.dispositivo.get_center_freq(
        ) + self.frecuencia_oscilador_local_lnb

    def esta_abierto(self):
        return self.dispositivo.device_opened

    def cerrar(self):
        if self.esta_abierto():
            self.dispositivo.close()