Sigma-Delta – Modulación con Python

Referencia: Leon-Couch, 3–8 Modulación Delta, p.192 ; Delta-sigma_modulation Wikipedia

La modulación Sigma-Delta (∑Δ ) codifica una señal analógica a digital generando una secuencia de +1 y -1 (impulsos) que representan la diferencia entre la señal analógica muestreada y la señal digital acumulada. Tiene aplicaciones en sintetizadores de frecuencia, fuentes de poder conmutadas y controladores de motor.

El sistema en diagrama de bloques en simulink se muestra en la figura:

sigma delta codec bloques

La señal de entrada (Sine Wave) se cuantifica en (Zero-Order Hold).

Luego se obtiene el signo (sign) de la diferencia entre la señal de entrada y la señal digital acumulada (∑) que genera la secuencia de +1 y -1 en la salida del codificador.

sigma delta codec grafica

El valor de la ganancia Δ=0.3 representa el valor del escalón de subida o bajada de la señal digital acumulada, representada en color magenta.

La secuencia de salida +1 y -1, de nuevo acumulada en el decodificador, permite obtener una versión digital cercana a la señal analógica inicial.


CODIFICADOR Sigma-Delta

La señal de entrada para el ejemplo tiene frecuencia fs=1 Hz, Δ=deltaY=0.3, rango [0,tn] hasta 2 segundos con divisiones k=40 en el rango de tiempo.

>>> 
rango [0,tn]:2
Secciones en el rango k:40
[ 0  1  1  1  1 -1  1 -1 -1 -1 -1 -1 -1 -1 -1
  1 -1  1  1  1  1  1  1  1  1 -1  1 -1 -1 -1
 -1 -1 -1 -1 -1  1 -1  1  1  1]
[  0.05   0.3   40.  ]

El script genera la gráfica y los archivos para datos y parámetros en formato texto.

La señal de entrada y los valores pueden ser modificados en el script adjunto:

# Modulacion Delta - Codificador
# entrada x(t), salida: y[n]
# propuesta:edelros@espol.edu.ec
import numpy as np
import matplotlib.pyplot as plt

# Definir la funcion de Entrada
def entradax(t,fs):
    x = np.sin(2*np.pi*fs*t)
    return(x)

# PROGRAMA para la modulación
# INGRESO
t0 = 0
tn = float(input('rango [0,tn]:'))
k  = int(input('Secciones en el rango k:'))

# PROCEDIMIENTO
# Analógica Referencia
fs = 1
m  = 500  # puntos en eje t para gráfico analógica
dm = (tn-t0)/m
t  = np.arange(0,tn,dm)  # eje tiempo analógica

xanalog = np.zeros(m, dtype=float)
for i in range(0,m):
    xanalog[i] = entradax(t[i],fs)

# Codificar Sigma-Delta
deltaY = 0.3          # Tamaño delta en eje Y
deltaT = (tn-t0)/k    # Tamaño delta en eje tiempo
td     = np.arange(0,tn,deltaT)    # tiempo muestreo
muestra  = np.zeros(k, dtype=float) # analógica para comparar
xdigital = np.zeros(k, dtype=float) # digital
ysalida  = np.zeros(k, dtype=int)   # Salida de +1|-1

td[0] = t0
muestra[0] = entradax(td[0],fs)
ysalida[0] = 0
for i in range(1,k):
    muestra[i] = entradax(td[i],fs) # referencia analógica
    diferencia = muestra[i]-xdigital[i-1]
    if (diferencia>0):
        bit = 1
    else:
        bit = -1
    xdigital[i] = xdigital[i-1]+bit*deltaY
    ysalida[i]  = bit
parametros = np.array([deltaT,deltaY,k])

# SALIDA
print(ysalida)
print(parametros)
np.savetxt('sigmadelta_datos.txt',ysalida,fmt='%i')
np.savetxt('sigmadelta_parametros.txt',parametros)

# Graficar
plt.figure(1)       # define la grafica
plt.suptitle('Codificador Sigma-Delta')

plt.subplot(211)    # grafica de 2x1 y subgrafica 1
plt.ylabel('x(t), x[n]')
xmax=np.max(xanalog)+0.1*np.max(xanalog) # rango en el eje y
xmin=np.min(xanalog)-0.1*np.max(xanalog)
plt.axis((t0,tn,xmin,xmax)) # Ajusta ejes
plt.plot(t,xanalog, 'g')
plt.axis((t0,tn,xmin,xmax))
plt.plot(td,xdigital,'bo')  # Puntos x[n]
plt.step(td,xdigital, where='post',color='m')

plt.subplot(212)    # grafica de 2x1 y subgrafica 2
plt.ylabel('y[n]')
plt.axis((0,k,-1.1,1.1))
plt.plot(ysalida, 'bo')     # Puntos y[n]
puntos = np.arange(0,k,1)     #posicion eje x para escalon
plt.step(puntos,ysalida, where='post')

plt.show()

Decodificador Sigma-Delta

Para observar el resultado, se decodifican los datos y se obtiene el siguiente resultado:

>>>
entrada: [ 0  1  1  1  1 -1  1 -1 -1 -1 -1 -1 -1 -1 -1
           1 -1  1  1  1  1  1  1  1  1 -1  1 -1 -1 -1
          -1 -1 -1 -1 -1  1 -1  1  1  1]
salida: 
[ 0.0000000e+00   3.0000000e-01   6.0000000e-01   9.0000000e-01
  1.2000000e+00   9.0000000e-01   1.2000000e+00   9.0000000e-01
  6.0000000e-01   3.0000000e-01  -1.1102230e-16  -3.0000000e-01
 -6.0000000e-01  -9.0000000e-01  -1.2000000e+00  -9.0000000e-01
 -1.2000000e+00  -9.0000000e-01  -6.0000000e-01  -3.0000000e-01
 -1.1102230e-16   3.0000000e-01   6.0000000e-01   9.0000000e-01
  1.2000000e+00   9.0000000e-01   1.2000000e+00   9.0000000e-01
  6.0000000e-01   3.0000000e-01  -1.1102230e-16  -3.0000000e-01
 -6.0000000e-01  -9.0000000e-01  -1.2000000e+00  -9.0000000e-01
 -1.2000000e+00  -9.0000000e-01  -6.0000000e-01  -3.0000000e-01]

sigma delta decodificador grafica

realizado usando el siguiente script de python:

# Modulacion Sigma-Delta Decodificador
#  entrada y[n], salida: x[n]
# propuesta:edelros@espol.edu.ec
import numpy as np
import matplotlib.pyplot as plt

# INGRESO
archivodatos = 'sigmadelta_datos.txt'
archivoparam = 'sigmadelta_parametros.txt'

# PROCEDIMIENTO
# Lectura de datos desde archivos
yentrada = np.loadtxt(archivodatos,dtype=int)
datos    = np.loadtxt(archivoparam,dtype=float)

deltaT = datos[0] # Tamaño delta en eje tiempo
deltaY = datos[1] # Tamaño delta en eje Y

# número de muestras
k = len(yentrada) 
xdigital = np.zeros(k, dtype=float)
punto    = np.zeros(k, dtype=int)   # número de muestra
td       = np.zeros(k, dtype=float) # tiempo muestreo

# DECOdifica Sigma-Delta
xdigital[0] = yentrada[0]
punto[0] = 0
td[0]    = 0
for i in range(1,k):
    punto[i] = i
    td[i]    = deltaT*i
    xdigital[i] = xdigital[i-1]+yentrada[i]*deltaY

# SALIDA
print('entrada:', yentrada)
print('salida:',xdigital,)

# Graficar
plt.figure(1)       # define la grafica
plt.suptitle('Decodifica Sigma_Delta')

plt.subplot(211)    # grafica de 2x1 y subgrafica 1
plt.ylabel('entrada: y[n]')
plt.axis((0,k-1,-1.1,1.1)) # Ajusta ejes
plt.plot(punto,yentrada,'bo') # Puntos y[n]
plt.step(punto,yentrada, where='post')

plt.subplot(212)    # grafica de 2x1 y subgrafica 2
plt.ylabel('salida: x[t]')
# rango en el eje y
xmax = np.max(xdigital)+0.1*np.max(xdigital)
xmin = np.min(xdigital)-0.1*np.max(xdigital)
plt.axis((0,td[k-1],xmin,xmax)) # Ajusta ejes
plt.plot(td,xdigital,'bo')
plt.step(td,xdigital, where='post', color='m')

plt.show()

Tarea

Realice observaciones cambiando:

a) la frecuencia de la señal de entrada,
b) el valor para deltaY
c) el rango tnd) el número de secciones en el tiempo
e) la forma de la señal de entrada a triangular, diente de sierra, exponencial periódica, etc.