【信号处理】Python实现BPSK、QPSK、8PSK、8QAM、16QAM、64QAM的调制和解调

简介: 使用Commpy开源包在Python中实现BPSK、QPSK、8PSK、8QAM、16QAM、64QAM等调制和解调方法的具体代码示例,但不包括8QAM的Commpy实现,以及一个完整的编码和解码示例。

1 引言

本文不涉及原理讲解,只提供实现方法。需要借助Commpy开源包去实现通信中的各种处理。

安装方法

方法一
pip install scikit-commpy
方法二
git clone https://github.com/veeresht/CommPy.git
cd CommPy
python setup.py install

2 实现

2.1 调制

import commpy as cpy
bits = np.random.binomial(n=1,p=0.5,size=(128))
Modulation_type ="BPSK"
if Modulation_type=="BPSK":
    bpsk = cpy.PSKModem(2)
  symbol = bpsk.modulate(bits)
  return symbol
elif Modulation_type=="QPSK":
    qpsk = cpy.PSKModem(4)
  symbol = qpsk.modulate(bits)
  return symbol
elif Modulation_type=="8PSK":
    psk8 = cpy.PSKModem(8)
  symbol = psk8.modulate(bits)
  return symbol
elif Modulation_type=="16QAM":
    qam16 = cpy.QAMModem(16)
  symbol = qam16.modulate(bits)
  return symbol
elif Modulation_type=="64QAM":
    qam64 = cpy.QAMModem(64)
  symbol = qam64.modulate(bits)
  return symbol

注意8QAM,不能用Commpy实现,实现如下

import numpy as np
import matplotlib.pyplot as plt
import math

def split_by_len(str, length):
    return [str[i:i+length] for i in range(0, len(str), length)]

def generate_8qam(signal):
    SAMP = 1
    fc = 4
    qam = []
    t = np.arange(0, SAMP)
    wave = []
    for i in range(8):
        if i % 2 == 0:
            amp = 0.5
        else:
            amp = 1
        wave.append(amp * np.exp(1j * (fc * np.pi * t/SAMP + math.floor(i/2) * np.pi/2)))

    s_bits = split_by_len(signal, 3)
    for s in s_bits:
        qam.extend(wave[int('0b' + s, 0)])
    qam = np.array(qam)
    return qam
bits = np.random.binomial(n=1,p=0.5,size=(128,))
if Modulation_type=="64QAM":
    signal = ''
    for i in range(bits.shape[0]):
        signal = signal+str(bits[i])
    symbol = generate_8qam(signal)
      return symbol

2.2 解调

# 和调制一样,需要先定义调制方法的类,再去调用解调的函数。
import commpy as cpy
bits = np.random.binomial(n=1,p=0.5,size=(128))
# Modem : QPSK
modem = mod.QAMModem(4)
signal = modem.modulate(bits)
modem.demodulate(signal, 'hard')

3 完整编码和解码的例子

来源Commpy 例子

# Authors: CommPy contributors
# License: BSD 3-Clause

from __future__ import division, print_function  # Python 2 compatibility

import math

import matplotlib.pyplot as plt
import numpy as np

import commpy.channelcoding.convcode as cc
import commpy.channels as chan
import commpy.links as lk
import commpy.modulation as mod
import commpy.utilities as util

# =============================================================================
# Convolutional Code 1: G(D) = [1+D^2, 1+D+D^2]
# Standard code with rate 1/2
# =============================================================================

# Number of delay elements in the convolutional encoder
memory = np.array(2, ndmin=1)

# Generator matrix
g_matrix = np.array((0o5, 0o7), ndmin=2)

# Create trellis data structure
trellis1 = cc.Trellis(memory, g_matrix)

# =============================================================================
# Convolutional Code 1: G(D) = [1+D^2, 1+D^2+D^3]
# Standard code with rate 1/2
# =============================================================================

# Number of delay elements in the convolutional encoder
memory = np.array(3, ndmin=1)

# Generator matrix (1+D^2+D^3 <-> 13 or 0o15)
g_matrix = np.array((0o5, 0o15), ndmin=2)

# Create trellis data structure
trellis2 = cc.Trellis(memory, g_matrix)

# =============================================================================
# Convolutional Code 2: G(D) = [[1, 0, 0], [0, 1, 1+D]]; F(D) = [[D, D], [1+D, 1]]
# RSC with rate 2/3
# =============================================================================

# Number of delay elements in the convolutional encoder
memory = np.array((1, 1))

# Generator matrix & feedback matrix
g_matrix = np.array(((1, 0, 0), (0, 1, 3)))
feedback = np.array(((2, 2), (3, 1)))

# Create trellis data structure
trellis3 = cc.Trellis(memory, g_matrix, feedback, 'rsc')

# =============================================================================
# Basic example using homemade counting and hard decoding
# =============================================================================

# Traceback depth of the decoder
tb_depth = None  # Default value is 5 times the number or memories

for trellis in (trellis1, trellis2, trellis3):
    for i in range(10):
        # Generate random message bits to be encoded
        message_bits = np.random.randint(0, 2, 1000)

        # Encode message bits
        coded_bits = cc.conv_encode(message_bits, trellis)

        # Introduce bit errors (channel)
        coded_bits[np.random.randint(0, 1000)] = 0
        coded_bits[np.random.randint(0, 1000)] = 0
        coded_bits[np.random.randint(0, 1000)] = 1
        coded_bits[np.random.randint(0, 1000)] = 1

        # Decode the received bits
        decoded_bits = cc.viterbi_decode(coded_bits.astype(float), trellis, tb_depth)

        num_bit_errors = util.hamming_dist(message_bits, decoded_bits[:len(message_bits)])

        if num_bit_errors != 0:
            print(num_bit_errors, "Bit Errors found!")
        elif i == 9:
            print("No Bit Errors :)")

# ==================================================================================================
# Complete example using Commpy features and compare hard and soft demodulation. Example with code 1
# ==================================================================================================

# Modem : QPSK
modem = mod.QAMModem(4)

# AWGN channel
channels = chan.SISOFlatChannel(None, (1 + 0j, 0j))

# SNR range to test
SNRs = np.arange(0, 6) + 10 * math.log10(modem.num_bits_symbol)

# Modulation function
def modulate(bits):
    return modem.modulate(cc.conv_encode(bits, trellis1, 'cont'))

# Receiver function (no process required as there are no fading)
def receiver_hard(y, h, constellation, noise_var):
    return modem.demodulate(y, 'hard')

# Receiver function (no process required as there are no fading)
def receiver_soft(y, h, constellation, noise_var):
    return modem.demodulate(y, 'soft', noise_var)

# Decoder function
def decoder_hard(msg):
    return cc.viterbi_decode(msg, trellis1)

# Decoder function
def decoder_soft(msg):
    return cc.viterbi_decode(msg, trellis1, decoding_type='soft')

# Build model from parameters
code_rate = trellis1.k / trellis1.n
model_hard = lk.LinkModel(modulate, channels, receiver_hard,
                          modem.num_bits_symbol, modem.constellation, modem.Es,
                          decoder_hard, code_rate)
model_soft = lk.LinkModel(modulate, channels, receiver_soft,
                          modem.num_bits_symbol, modem.constellation, modem.Es,
                          decoder_soft, code_rate)

# Test
BERs_hard = model_hard.link_performance(SNRs, 10000, 600, 5000, code_rate)
BERs_soft = model_soft.link_performance(SNRs, 10000, 600, 5000, code_rate)
plt.semilogy(SNRs, BERs_hard, 'o-', SNRs, BERs_soft, 'o-')
plt.grid()
plt.xlabel('Signal to Noise Ration (dB)')
plt.ylabel('Bit Error Rate')
plt.legend(('Hard demodulation', 'Soft demodulation'))
plt.show()
目录
相关文章
|
5月前
|
数据可视化 算法 Python
【数字通信革命】深入剖析Python实现BPSK、QPSK到QAM信号调制的奥秘,解锁高速数据传输的密钥!
【8月更文挑战第2天】在通信系统中,信号调制至关重要,它将信息嵌入载波信号中以便传输。本文通过Python实现三种基本调制技术:BPSK、QPSK和16-QAM,并提供示例代码。首先需安装NumPy、SciPy和Matplotlib库。BPSK是最简单的相位调制,每个符号携带一位信息;QPSK则每个符号携带两位信息,通过四种相位表示;16-QAM结合幅度和相位调制,每个符号携带更多比特信息。本文提供的代码演示了这些调制方式的实现过程,并利用Matplotlib可视化结果。了解这些调制技术有助于深入探索信号处理领域。
205 18
|
5月前
|
Python
【信号处理】python按原理实现BPSK、QPSK、QAM信号调制
本文提供了两种不同的方法来实现16-QAM(正交幅度调制)的调制和解调过程,一种是使用commpy库,另一种是通过手动定义映射字典来实现。
391 8
|
5月前
|
数据可视化 Python
【Python】Python 仿真OFDM发射机、信道和接收机-实现多种调制方式
文章介绍了如何使用Python和Commpy工具包实现OFDM通信系统的仿真,包括发射机、信道和接收机的过程,并支持BPSK、QPSK、8PSK、16QAM、64QAM等多种调制方式,同时展示了导频插入、信道冲击响应、星座映射的可视化,并计算了系统的误比特率。
223 0
|
6月前
|
Python
`scipy.signal`模块是SciPy库中的一个子模块,它提供了信号处理、滤波、频谱分析等功能。这个模块包含了许多用于信号处理的函数和类,其中`butter()`和`filtfilt()`是两个常用的函数。
`scipy.signal`模块是SciPy库中的一个子模块,它提供了信号处理、滤波、频谱分析等功能。这个模块包含了许多用于信号处理的函数和类,其中`butter()`和`filtfilt()`是两个常用的函数。
|
8月前
|
Serverless Python
SciPy信号处理实战:从滤波到频谱分析
【4月更文挑战第17天】本文展示了如何使用Python的SciPy库进行信号处理,包括滤波和频谱分析。首先,通过`scipy.signal`模块实现滤波,如低通滤波器设计和应用,以去除噪声或提取特定频率成分。接着,利用傅里叶变换和`fft`函数进行频谱分析,揭示信号的频率成分和功率分布。通过实例代码,读者可了解从滤波到频谱分析的完整过程,从而在实际项目中有效处理和分析信号。
|
8月前
|
数据可视化 数据挖掘 Python
Scipy 中级教程——信号处理
Scipy 中级教程——信号处理【1月更文挑战第8篇】
385 2
|
1月前
|
人工智能 数据可视化 数据挖掘
探索Python编程:从基础到高级
在这篇文章中,我们将一起深入探索Python编程的世界。无论你是初学者还是有经验的程序员,都可以从中获得新的知识和技能。我们将从Python的基础语法开始,然后逐步过渡到更复杂的主题,如面向对象编程、异常处理和模块使用。最后,我们将通过一些实际的代码示例,来展示如何应用这些知识解决实际问题。让我们一起开启Python编程的旅程吧!
|
1月前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
21天前
|
Unix Linux 程序员
[oeasy]python053_学编程为什么从hello_world_开始
视频介绍了“Hello World”程序的由来及其在编程中的重要性。从贝尔实验室诞生的Unix系统和C语言说起,讲述了“Hello World”作为经典示例的起源和流传过程。文章还探讨了C语言对其他编程语言的影响,以及它在系统编程中的地位。最后总结了“Hello World”、print、小括号和双引号等编程概念的来源。
105 80
|
10天前
|
Python
[oeasy]python055_python编程_容易出现的问题_函数名的重新赋值_print_int
本文介绍了Python编程中容易出现的问题,特别是函数名、类名和模块名的重新赋值。通过具体示例展示了将内建函数(如`print`、`int`、`max`)或模块名(如`os`)重新赋值为其他类型后,会导致原有功能失效。例如,将`print`赋值为整数后,无法再用其输出内容;将`int`赋值为整数后,无法再进行类型转换。重新赋值后,这些名称失去了原有的功能,可能导致程序错误。总结指出,已有的函数名、类名和模块名不适合覆盖赋新值,否则会失去原有功能。如果需要使用类似的变量名,建议采用其他命名方式以避免冲突。
30 14