2020年6月19日 星期五

Signal Generators (en)

(Including AD9833AD9834AD9850ADF4351)


Why this

 I started learning SDR recently, and need to use signal generator . Some modules on the market have sophisticated functions, but are usually expensive. AD9833  is a cheap and popular DDS / signal generator module. I bought a few and tested with home-brew driver for Python, so that I can use  PC (Windows / Linux, with USB-SPI converter), Raspberry Pi , ESP32  to control AD9833.

The GitHub repository is  here , which also includes drivers for several popular signal generator modules AD9833,  AD9834,  AD9850,  ADF4351) . 

Categories of signal generators

I personally divide signal generators into three categories:

1. Independent set:
There are many models ( examples ), and the functions will be slightly different depending on the application field. 
Pros: 
  • Operates independently, without relying on and consuming PC resources.
  • It is composed of many hardware components and has high operating efficiency.
  • Sophisticated functionalities.
Cons:  
  • Although with sophisticated functionalities, it is still limited, and expansion is not easy/free.
  • Some models come with API/protocol  for communicating with the PC, but learning  curve may be steep.
  • The driver / API / utilities provided by the manufacturer may not cross-platform (Windows / Linux).
  • It cannot be operated with MCU (eg. ESP32, Arduino).
  • Usually expensive.

2. Signal generator in an USB dongle ( example ):
Pros: 
  • Small and very portable.
  • With dedicated hardware components for performance. 
  • It can be controlled by software on PC, and therefore flexible.
Cons:
  • Usually with limited functionality.
  • It still needs to be controlled by the PC, consume some resources. 
  • The driver / utilities may not cross OS (Windows / Linux).
  • It cannot be used with ESP32 and Arduino.
  • Not quite cheap.
3.  Arduino-like based signal generator ( example ):
Pros:
  •   Can operate independently, without consuming PC resources.
  •   Cheap.
Cons:
  •   Not easy to interface with PC.
  •   Operating independently, but may not be easy to co-operate with other devices.
  •   Limited functionality.
There are many examples on the Internet where Arduino / ESP32 is used with the AD9833 module. This is also what I tried to do at the beginning.

Device driver development models
To develop a device driver in order to "using Arduino /  ESP32 or other controller with AD9833 to generate various signals ", we can takes one of following development models :
1. Do it all on a real device:
Write/compile the program on the PC and upload it to the device (Arduino /  ESP32 ) which controls AD9833 For debugging, insert commands such as "print" into the program to display the status. Repeat the above steps until bugs are fixed. 
Pros: 
  • Tested in a real device, the result is absolutely real. 
Cons: 
  • It is necessary to insert the many "print" instructions one by one at the points of interest, and then recompile and upload again, which is cumbersome. 
  • Can't set break points, no way to pause the running program and inspect the status and value of variables.
  • Not possible to dynamically modify the variable value or re-direct the flow. The only way to do that is to revise, re-compile, and upload again, which takes time and patience.
  • Low cross-platform portability, driver developed for Arduino may not be used directly on ESP32, Raspberry Pi, or PC.   
Pros: 
  • No need to manually add "print" instructions. 
  • Break points can be set to pause the program to check the status.
  • Value of variable and flow can be dynamically modified. 
Cons:
  • With complex configuration and operations, the learning  curve may be steep.
  • Not every MCU supports JTag.   
  • Not every IDE supports JTag.   
  • Low cross-platform portability, driver developed for Arduino may not be used directly on ESP32, Raspberry Pi, or PC.    

Goals
 I use ESP32+ (Micro)Python most of the time, so I will skip Arduino here.
The goals of this project are as following:
  • To build drivers, with which you can use ESP32 / Raspberry Pi to drive AD9833 module to generate signals.
  • PC (Windows / Linux) also can be used to control the AD9833, therefore enormous resources on the PC side are available to AD9833, many tasks are possible, such as sending data from PC via the AD9833 generated signal.
  • One or many AD9833 modules can be used for variety of  modulation (BFSK, BPSK, QPSK, IQ, FM, PM, OOK, DTMF) .
  • The driver can be used to control AD9833, across OS (Windows / Linux) and hardware (PC / Raspberry Pi / ESP32).
  • During the driver development:
    • No need to upload code to MCU repeatedly .
    • Break points can be set to pause the code, variables and flow can be inspected and modified. JTag is not required, therefore there is not learning curve.

  • Use Python
    • OS is somewhat abstract to Python. With minor to no modification , the same Python code is likely to work on  Windows / Linux,  PC / Raspberry / ESP32.
  • Use Adapter design pattern :
    • Wrap the bus (SPI / I2C / GPIO) on different platforms into adapters which obey an unified interface definition, so that the same driver can be used with different OS (Windows / Linux) and hardware (PC / Raspberry Pi / ESP32) , by selecting corresponding adapter, the required adjustment is minimized.
  • Register as a software class:
    • With software classes of registers, according to the specification of AD9833, reading/writing of register is no longer tedious. Only the name of the field needs to be specified, no need to calculate how many bits to shift. For example, to control the SLEEP1 field, just:
      • def _enable_internal_clock(self, value = True):
            self.control_register.elements['SLEEP1'].value = int(not bool(value))
            self._update_control_register()
    
    
    • Status of a register can be "printed" , for example:
    • ad.control_register.print()
      
      << Control >>    :  ('0x2000', '0b10000000000000')
      [ D15 ]        :  0
      [ D14 ]        :  0
      [ B28 ]        :  1
      [ HLB ]        :  0
      [ FSELECT ]    :  0
      [ PSELECT ]    :  0
      [ PIN_SW ]     :  0
      [ Reset ]      :  0
      [ SLEEP1 ]     :  0
      [ SLEEP12 ]    :  0
      [ OPBITEN ]    :  0
      [ SIGN_PIB ]   :  0
      [ DIV2 ]       :  0
      [ Reserved_2 ] :  0
      [ Mode ]       :  0
      [ Reserved_0 ] :  0
    • Registers value comparision:
      • We can compare two sets of register values, showing all register fields or just the mis-matched ones. This is very useful during device driver development.
  • Directly control AD9833 with PC
    • Use USB-SPI converter (such as FT232H or FX2LP ) , so we can control AD9833 directly from PC using SPI interface.
    • With the Bridges package, pretend your PC as a Raspberry Pi or an ESP32:
      • Let a PC with USB-SPI converter have the SPI function of  the same interface definition with that on ESP32 / Raspberry Pi, so we can pretend a PC  as if it's a Raspberry Pi / ESP32, so the driver developed can be copied directly to the PC / ESP32 / Raspberry Pi  with no modification required .
      • That is to say, existing Python drivers of AD9833 on Raspberry Pi or ESP32 can be used on PC with little or no modification.
    • Impact on driver development:
      • Develop the program on the PC and directly control the AD9833 for testing, without repeatedly uploading the code to MCU.
      • Taking advantage of the powerful development environment on PC, such as advanced IDEs (for example:  PyCharm ) , you can set breakpoints, pause and check the status, view or modify variable values whenever you want.
      • You can test and use the AD9833 with Jupyter Notebook ,  development and documentation are both taken care of at the same time.
    • Impact on the usage of AD9833:
      • Easy connecting AD9833 with PC.
      • Enormous resources on the PC side now are available to a signal generator like AD9833, which can greatly expend the functionality of a signal generator. 
        • Data can be prepared with Numpy and various Python modules.
        • You can send modulated information via AD9833 directly from PC .
      • Like SDR,  now AD9833 can be controlled without a separated MCU. Total cost is lower .
      • In addition to the AD9833, other devices can be controlled by a PC in the same way for collaborative operation (such as test-automation).

Test Results
Basic functional tests:
Waveform manipulation
  • Tested with this notebook:
  • Frequency sweeping:
Control AD9833 with PC + FT232H (USB-SPI converter) 
using Jupyter notebook

Control AD9833 with ESP32 
(which in turns is controlled via Jupyter + MicroPython Remote Kernel)

  • Waveform juggling:

Control AD9833 with PC + FT232H (USB-SPI converter) 
using Jupyter notebook

Control AD9833 with ESP32 
(which in turns is controlled via Jupyter + MicroPython Remote Kernel)

 Modulations 



  • IQ (using two AD9833 modules)





  • DTMF  (using two AD9833 modules):



Other modules:
  • AD9834

  • AD9850 (I forgot to record video)
  • ADF4351



Dependencies:

沒有留言: