Using a Raspberry Pi to Control an Ultram VCO

Post Reply
G8GKQ
Site Admin
Posts: 2798
Joined: Sun Mar 22, 2009 1:21 pm

Using a Raspberry Pi to Control an Ultram VCO

Post by G8GKQ » Mon Feb 24, 2014 1:35 pm

I have developed a very simple program in Python to control an Ultram VCO from a Raspberry Pi. In preparation for a forthcoming CQ-TV article, here is the code.

Code: Select all

#!/usr/bin/env python

# Simple Python Program to program ADF4360-X VCO from RPi
# Written by David Crump, G8GKQ, 22 Feb 14.
# Feel free to modify, copy, use or abuse as you wish

import RPi.GPIO as GPIO
import os
import time


GPIO.setmode(GPIO.BCM)

DEBUG = 1 # set to 0 for quiet operation, 1 for verbose

# ------------------- DEFINE delay  ------------------

def delay(delayms): #in millisec
    time.sleep(delayms/1000)
    return 0

# ------------------- END OF delay  ------------------

# ------------------- DEFINE sendchar  ------------------

# Ouputs one hex 4-bit character MSB first
# Entry and exit with clock low after delay

def sendchar(hexchar): 

# first convert hexchar to integer (hexint)

    if hexchar == "0":
        hexint = 0
    elif hexchar == "1":
        hexint = 1
    elif hexchar == "2":
        hexint = 2
    elif hexchar == "3":
        hexint = 3
    elif hexchar == "4":
        hexint = 4
    elif hexchar == "5":
        hexint = 5
    elif hexchar == "6":
        hexint = 6
    elif hexchar == "7":
        hexint = 7
    elif hexchar == "8":
        hexint = 8
    elif hexchar == "9":
        hexint = 9
    elif hexchar == "a" or hexchar == "A":
        hexint = 10
    elif hexchar == "b" or hexchar == "B":
        hexint = 11
    elif hexchar == "c" or hexchar == "C":
        hexint = 12
    elif hexchar == "d" or hexchar == "D":
        hexint = 13
    elif hexchar == "e" or hexchar == "E":
        hexint = 14
    elif hexchar == "f" or hexchar == "F":
        hexint = 15
    else:
        print('Invalid Hex Character')
        return

    commandout = hexint
    commandout <<= 4    # shift left 4 as we only need to send 4 bits here
    for i in range(4):
            if (commandout & 0x80): 
                    GPIO.output(SPIMOSI, True)
                    if DEBUG == 1:
                        print('Sent 1')
            else:   
                    GPIO.output(SPIMOSI, False)
                    if DEBUG == 1:
                        print('Sent 0')
            commandout <<= 1 # Shift left 1
            delay(1)

            GPIO.output(SPICLK, True)
            delay(2)
                
            GPIO.output(SPICLK, False)
            delay(1)
                
# ------------------- END OF sendchar  ------------------

# ------------------- DEFINE send6string  ------------------
                
def send6string(hex6string):
# sets load enable low (false)
        GPIO.output(SPICS, False)     # bring CS low

# sets clock low
        GPIO.output(SPICLK, False)  # start clock low
        
# peels first char off string
        hexchar1 = hex6string[0:1]
# calls sendchar
        sendchar(hexchar1)
#select last 5 chars
        hex5string = hex6string[-5:]
        
# peels second char off string
        hexchar2 = hex5string[:1]
# calls sendchar
        sendchar(hexchar2)
#select last 4 chars
        hex4string = hex5string[-4:]
        
# peels third char off string
        hexchar3 = hex4string[:1]
# calls sendchar
        sendchar(hexchar3)
#select last 3 chars
        hex3string = hex4string[-3:]
        
# peels fourth char off string
        hexchar4 = hex3string[:1]
# calls sendchar
        sendchar(hexchar4)
#select last 2 chars
        hex2string = hex3string[-2:]
        
# peels fifth char off string
        hexchar5 = hex2string[:1]
# calls sendchar
        sendchar(hexchar5)
#select last char
        hex1string = hex2string[-1:]
        
# peels sixth char off string
        hexchar6 = hex1string
# calls sendchar
        sendchar(hexchar6)
        

# sets load enable high to load data
        GPIO.output(SPICS, True)

# ------------------- END OF send6string  ------------------

# ------------------- DEFINE setparams  ------------------

# This sends the three 6-character strings to the VCO in sequence

def setparams(RCounter, Control, NCounter):
    send6string(RCounter)
#   no delay
    send6string(Control)
    delay(5)                  # 5 ms delay
    send6string(NCounter)

# ------------------- END OF setparams  ------------------



# ------------------- MAIN PROG STARTS HERE ------------------

if DEBUG == 1:
    print ('Started')
    GPIO.setwarnings(True)
else:
    GPIO.setwarnings(False)
    
GPIO.cleanup()    # Reset All the ports

# Set the Pi GPIO ports for the SPI Bus

SPICLK = 11  #  Pi pin 23 to old PIC pin 6
SPIMISO = 9  #  Pi pin 21 not used
SPIMOSI = 10 #  Pi pin 19 to old PIC pin 7
SPICS = 8    #  Pi pin 24 to old PIC pin 3
# Ground      Pi pin 6 to old PIC pin 8

# Set up the SPI interface pins

GPIO.setup(SPIMOSI, GPIO.OUT)
GPIO.setup(SPIMISO, GPIO.IN)
GPIO.setup(SPICLK, GPIO.OUT)
GPIO.setup(SPICS, GPIO.OUT)

# Send the parameters required:

#     Examples:

#     setparams('300191','9FE924','018652') # Powerdown
#     setparams('300191','8FE924','018652') # 1250 MHz, 100KHz step
#     setparams('300191','8FE924','018E3A') # 1275 MHz, 100KHz step
#     setparams('300051','8FF924','004F5A') # 1275 MHz, 500KHz step
#     setparams('300191','8FE924','017702') # 1200 MHz, 100KHz step
#     setparams('300191','8FE924','01B542') # 1400 MHz, 100KHz step

setparams('300191','8FE924','018652') # 1250 MHz, 100KHz step

if DEBUG == 1:
    print ('Finished')

# GPIO.cleanup()   Don't clean-up here or ports go open circuit
#                  and noise resets VCO

# ------------------- MAIN PROG ENDS HERE ------------------
Please feel free to try it, but recognise that the code is simple, understandable and could be improved!

Edit: I have posted an improved version below.

Dave
G8GKQ

f5oeo
Posts: 70
Joined: Mon Mar 10, 2014 5:46 pm

Re: Using a Raspberry Pi to Control an Ultram VCO

Post by f5oeo » Mon Mar 17, 2014 11:57 am

Great job Dave...Hope to integrate soon this process with the stand alone RPI Encoder I just begin to describe here :
http://www.vivadatv.org/viewtopic.php?f=75&t=293

73's Evariste F5OEO

G8GKQ
Site Admin
Posts: 2798
Joined: Sun Mar 22, 2009 1:21 pm

Re: Using a Raspberry Pi to Control an Ultram VCO

Post by G8GKQ » Thu May 08, 2014 4:52 am

After some problems with driving a 437 MHz Ultram VCO (caused by the print commands taking too long and causing bit-bang commands to be missed), I have developed a new version below. It does not output anything to the terminal screen, but runs much faster.

Code: Select all

#!/usr/bin/env python

# Simple Python Program to program ADF4360-X VCO from RPi
# Written by David Crump, G8GKQ, 22 Feb 14.
# Feel free to modify, copy, use or abuse as you wish

# Revised on 8 May 14 to take out print functions that were
# causing bit-bang timing errors.

import RPi.GPIO as GPIO
import os
import time


GPIO.setmode(GPIO.BCM)

# ------------------- DEFINE delay  ------------------

def delay(delayms): #in millisec
    time.sleep(delayms/1000)
    return 0

# ------------------- END OF delay  ------------------

# ------------------- DEFINE sendchar  ------------------

# Ouputs one hex 4-bit character MSB first
# Entry and exit with clock low after delay

def sendchar(hexchar): 

# first convert hexchar to integer (hexint)

    if hexchar == "0":
        hexint = 0
    elif hexchar == "1":
        hexint = 1
    elif hexchar == "2":
        hexint = 2
    elif hexchar == "3":
        hexint = 3
    elif hexchar == "4":
        hexint = 4
    elif hexchar == "5":
        hexint = 5
    elif hexchar == "6":
        hexint = 6
    elif hexchar == "7":
        hexint = 7
    elif hexchar == "8":
        hexint = 8
    elif hexchar == "9":
        hexint = 9
    elif hexchar == "a" or hexchar == "A":
        hexint = 10
    elif hexchar == "b" or hexchar == "B":
        hexint = 11
    elif hexchar == "c" or hexchar == "C":
        hexint = 12
    elif hexchar == "d" or hexchar == "D":
        hexint = 13
    elif hexchar == "e" or hexchar == "E":
        hexint = 14
    elif hexchar == "f" or hexchar == "F":
        hexint = 15
    else:
        print('Invalid Hex Character')
        return

    commandout = hexint

    for i in range(4):
        if (commandout & 0x08): 
                GPIO.output(SPIMOSI, True)
        else:   
                GPIO.output(SPIMOSI, False)

        commandout <<= 1 # Shift left 1
        delay(1)

        GPIO.output(SPICLK, True)
        delay(2)
                
        GPIO.output(SPICLK, False)
        delay(1)
                
# ------------------- END OF sendchar  ------------------

# ------------------- DEFINE send6string  ------------------
                
def send6string(hex6string):
# sets load enable low (false)
        GPIO.output(SPICS, False)     # bring CS low

# sets clock low
        GPIO.output(SPICLK, False)  # start clock low
        
# peels first char off string
        hexchar1 = hex6string[0:1]
# calls sendchar
        sendchar(hexchar1)
#select last 5 chars
        hex5string = hex6string[-5:]
        
# peels second char off string
        hexchar2 = hex5string[:1]
# calls sendchar
        sendchar(hexchar2)
#select last 4 chars
        hex4string = hex5string[-4:]
        
# peels third char off string
        hexchar3 = hex4string[:1]
# calls sendchar
        sendchar(hexchar3)
#select last 3 chars
        hex3string = hex4string[-3:]
        
# peels fourth char off string
        hexchar4 = hex3string[:1]
# calls sendchar
        sendchar(hexchar4)
#select last 2 chars
        hex2string = hex3string[-2:]
        
# peels fifth char off string
        hexchar5 = hex2string[:1]
# calls sendchar
        sendchar(hexchar5)
#select last char
        hex1string = hex2string[-1:]
        
# peels sixth char off string
        hexchar6 = hex1string
# calls sendchar
        sendchar(hexchar6)

# Set Data low (for consistency)
        GPIO.output(SPIMOSI, False)
        
# Wait for settling time before loading data
        delay(1)
        
# sets load enable high to load data
        GPIO.output(SPICS, True)

# ------------------- END OF send6string  ------------------

# ------------------- DEFINE setparams  ------------------

# This sends the three 6-character strings to the VCO in sequence

def setparams(RCounter, Control, NCounter):
    send6string(RCounter)
    delay(5)                  # 5 ms delay
    send6string(Control)
    delay(5)                  # 5 ms delay
    send6string(NCounter)

# ------------------- END OF setparams  ------------------



# ------------------- MAIN PROG STARTS HERE ------------------

GPIO.setwarnings(False)
    
GPIO.cleanup()    # Reset All the ports

# Set the Pi GPIO ports for the SPI Bus

SPICLK = 11  #  Pi pin 23 to old PIC pin 6
SPIMISO = 9  #  Pi pin 21 not used
SPIMOSI = 10 #  Pi pin 19 to old PIC pin 7
SPICS = 8    #  Pi pin 24 to old PIC pin 3
# Ground        Pi pin 6  to old PIC pin 8

# Set up the SPI interface pins

GPIO.setup(SPIMOSI, GPIO.OUT)
GPIO.setup(SPIMISO, GPIO.IN)
GPIO.setup(SPICLK, GPIO.OUT)
GPIO.setup(SPICS, GPIO.OUT)

# Send the parameters required:

# Examples:

#     setparams('R Register,'Function','N Register')  Helper
#     setparams('300191','9FE924','018652') # Powerdown

# ADF4360-7

setparams('000029','06E124','003616') # 437 MHz, 1MHz step

# ADF4360-5

#     setparams('300191','8FE924','018652') # 1250 MHz, 100KHz step
#     setparams('300191','8FE924','018E3A') # 1275 MHz, 100KHz step
#     setparams('300051','8FF924','004F5A') # 1275 MHz, 500KHz step
#     setparams('300191','8FE924','017702') # 1200 MHz, 100KHz step
#     setparams('300191','8FE924','01B542') # 1400 MHz, 100KHz step

# ADF4360-3

#     setparams('3000C9','8FF108','011922') # 1800 MHz, 200KHz step
#     setparams('3000C9','8FF108','00FA02') # 1600 MHz, 200KHz step
#     setparams('3000C9','8FF108','013842') # 2000 MHz, 200KHz step

# ------------------- MAIN PROG ENDS HERE ------------------
Dave
G8GKQ

Post Reply

Return to “DigiLite”