Raspberry Pi Pico for Radio Amateurs 9783895764813, 3895764817

Although much classical HF and mobile equipment is still in use by large numbers of amateurs, the use of computers and d

1,151 292 11MB

English Pages 310 Year 2021

Report DMCA / Copyright

DOWNLOAD FILE

Polecaj historie

Raspberry Pi Pico for Radio Amateurs
 9783895764813, 3895764817

Table of contents :
Contents
Preface
Chapter 1 • Raspberry Pi Pico Hardware
1.1 Overview
1.2 Pico hardware module
1.3 Comparison with the Arduino UNO
1.4 Operating conditions and powering the Pico
1.5 Pinout of the RP2040 microcontroller and Pico module
1.6 Other RP2040 microcontroller-based boards
1.6.1 Adafruit Feather RP2040
1.6.2 Adafruit ItsyBitsy RP2040
1.6.3 Pimoroni PicoSystem
1.6.4 Arduino Nano RP2040 Connect
1.6.5 SparkFun Thing Plus RP2040
1.6.6 Pimoroni Pico Explorer Base
1.6.7 SparkFun MicroMod RP2040 Processor
1.6.8 SparkFun Pro Micro RP2040
1.6.9 Pico RGB Keypad Base
1.6.10 Pico Omnibus
1.6.11 Pimoroni Pico VGA Demo Base
1.6.12 Tiny 2040
Chapter 2 • Raspberry Pi Pico Programming
2.1 Overview
2.2 Installing MicroPython on Pico
2.2.1 Using a Raspberry Pi 4 to help install MicroPython on the Pico
2.2.2 Using a PC (Windows 10) to help install MicroPython on Pico
Chapter 3 • Simple Programs – Software Only
3.1 Overview
3.2 Examples
3.2.1 Average of two numbers read from the keyboard
3.2.2 Average of 10 numbers read from the keyboard
3.2.3 Surface area of a cylinder
3.2.4 ºC to ºF conversion
3.2.5 Surface area and volume of a cylinder – user function
3.2.6 Table of squares of numbers
3.2.7 Table of trigonometric sine
3.2.8 Table of trigonometric sine, cosine and tangent
3.2.9 Trigonometric function of a required angle
3.2.10 Words in reverse order
3.2.11 Calculator
3.2.12 Dice
3.2.13 Sorting lists
3.2.14 File processing — writing
3.2.15 File processing — reading
3.2.16 Squares and cubes of numbers
3.2.17 Multiplication timetable
3.2.18 Odd or even?
3.2.19 Binary, octal, and hexadecimal
3.2.20 Add two matrices
3.2.21 Shapes
Chapter 4 • Amateur Radio Programs — Software Only
4.1 Overview
4.2 Examples
4.2.1 4-band resistor color code identifier
4.2.2 4-band resistor color code identifier including small resistors
4.2.3 Resistive potential divider
4.2.4 Resistive attenuator design — equal source & load resistances
4.2.5 Resistive attenuator design — unequal source & load resistances
4.2.6 Zener diode based voltage regulator
4.2.7 RC circuit frequency response
4.2.8 Resonance in series RLC circuits
4.2.9 Calculating the inductance of a single-layer coil
4.2.10 Constructing a single-layer coil for required inductance
4.2.11 Bipolar junction transistor (BJT) voltage divider biasing
4.2.12 Designing a common-emitter BJT transistor amplifier circuit
4.2.13 Designing active low-pass filters
4.2.14 Quarter-wave vertical antenna length
4.2.15 The '555' Monostable / bistable / astable chip
4.2. Impedance matching
Chapter 5 • Simple Hardware-Based Projects
5.1 Overview
5.2 Project 1: Flashing the on-board LED
5.3 Project 2: External flashing LED
5.4 Project 3: Changing the LED flashing rate using pushbutton interrupts
5.5 Project 4: Binary counting LEDs
5.6 Using parallel LCDs
5.7 Project 5: LCD functions — displaying text
5.8 Project 6: Seconds counter – Parallel LCD
5.9 Using I2C LCDs
5.10 Project 7: Seconds counter with I2C LCD
Chapter 6 • Amateur Radio Hardware-based Projects
6.1 Overview
6.2 Project 1: Station mains On/Off power control
6.3 Project 2: Station clock
6.4 Project 3: Station temperature and humidity
6.5 Project 4: Station geographical coordinates
6.6 Waveform generation – using software
6.6.1 Project 5: Generating a squarewave signal with amplitude under +3.3 V
6.6.2 Project 6: Generating fixed voltages
6.6.3 Project 7: Generating a sawtooth signal
6.6.4 Project 8: Generating a triangular-wave signal
6.6.5 Project 9: Arbitrary periodic waveform
6.6.6 Project 10: Generating a sinewave signal
6.6.7 Project 11: Generating an accurate sinewave signal using timer interrupts
6.7 Waveform generation — using hardware
6.7.1 Project 12: Fixed-frequency waveform generator
6.7.2 Project 13: Generating waveforms with frequency-entry on keypad and LCD readout
6.8 Project 14: Frequency counter
6.9 Voltmeter – Ammeter – Ohmmeter – Capacitance meter
6.9.1 Project 15: Voltmeter
6.9.2 Project 16: Ammeter
6.9.3 Project 17: Ohmmeter
6.9.4 Project 18: Capacitance meter
6.10 Project 19: RF power meter
6.10.1 RF attenuators
6.10.2 dB, dBm, and W?
6.11 Project 20: Using the RadioStation Click board
6.12 Morse Code exercisers
6.12.1 Project 21: Characters entered by the user
6.12.2 Project 22: Sending randomly generated characters
6.12.3 Project 23: Setting Morse speed using an LCD and a rotary encoder
6.13 Project 24: Relay sequencer with time delays
6.14 Project 25: FM radio with the Raspberry Pi Pico
6.14.1 Project 26: Modified FM Radio - increasing the output signal level – connecting a loudspeaker
6.14.2 Project 27: FM radio using an LCD and external buttons
6.14.3 Project 28: FM radio using an LCD and rotary encoder
6.15 Project 29: Measure the frequency and duty cycle of a PWM waveform – screen display
6.16 Project 30: Measure the frequency and duty cycle of a PWM waveform – LCD display
6.17 Raspberry Pi Pico Bluetooth interface
6.17.1 Project 31: Controlling an LED from a smartphone using Bluetooth
6.18 Project 32: Station security
6.19 Project 33: Generating accurate squarewave signals using the Raspberry Pi Pico State Machines
6.20 Project 34: Using Wi-Fi with the Raspberry Pi Pico – Controlling an LED from a smartphone
6.21 Project 35: Audio amplifier module with rotary encoder volume control
6.22 Project 36: Morse decoder
6.23 Raspberry Pi Pico RTL-SDR
6.24 Project 37: Using the FS1000A 433 MHz transmitter/receiver pair
Chapter 7 • Running a Program Automatically after the Raspberry Pi Pico Boots
APPENDIX
Parts Used in Projects
Index

Citation preview

books

Raspberry Pi Pico for Radio Amateurs Program and build RPi Pico-based ham station utilities, tools, and instruments

Dogan Ibrahim, G7SCU

Raspberry Pi Pico for Radio Amateurs Program and build RPi Pico-based hams station utilities, tools, and instruments

● Dogan Ibrahim, G7SCU

● This is an Elektor Publication. Elektor is the media brand of Elektor International Media B.V.

PO Box 11, NL-6114-ZG Susteren, The Netherlands Phone: +31 46 4389444

● All rights reserved. No part of this book may be reproduced in any material form, including photocopying, or

storing in any medium by electronic means and whether or not transiently or incidentally to some other use of this publication, without the written permission of the copyright holder except in accordance with the provisions of the Copyright Designs and Patents Act 1988 or under the terms of a licence issued by the Copyright Licencing Agency Ltd., 90 Tottenham Court Road, London, England W1P 9HE. Applications for the copyright holder's permission to reproduce any part of the publication should be addressed to the publishers.

● Declaration

The Author and Publisher have used their best efforts in ensuring the correctness of the information contained in this book. They do not assume, and hereby disclaim, any liability to any party for any loss or damage caused by errors or omissions in this book, whether such errors or omissions result from negligence, accident, or any other cause. All the programs given in the book are Copyright of the Author and Elektor International Media. These programs may only be used for educational purposes. Written permission from the Author or Elektor must be obtained before any of these programs can be used for commercial purposes.

● British Library Cataloguing in Publication Data

A catalogue record for this book is available from the British Library

● ISBN 978-3-89576-481-3 Print

ISBN 978-3-89576-482-0 eBook

● © Copyright 2021: Elektor International Media B.V. Editor: Jan Buiting

Prepress Production: D-Vision, Julian van den Berg

Elektor is part of EIM, the world's leading source of essential technical information and electronics products for pro engineers, electronics designers, and the companies seeking to engage them. Each day, our international team develops and delivers high-quality content - via a variety of media channels (including magazines, video, digital media, and social media) in several languages - relating to electronics design and DIY electronics. www.elektormagazine.com

●4

Contents Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Chapter 1 • Raspberry Pi Pico Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.2 Pico hardware module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 1.3 Comparison with the Arduino UNO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 1.4 Operating conditions and powering the Pico . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 1.5 Pinout of the RP2040 microcontroller and Pico module . . . . . . . . . . . . . . . . . . . . 16 1.6 Other RP2040 microcontroller-based boards . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 1.6.1 Adafruit Feather RP2040 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 1.6.2 Adafruit ItsyBitsy RP2040 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 1.6.3 Pimoroni PicoSystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 1.6.4 Arduino Nano RP2040 Connect . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 1.6.5 SparkFun Thing Plus RP2040 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 1.6.6 Pimoroni Pico Explorer Base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 1.6.7 SparkFun MicroMod RP2040 Processor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 1.6.8 SparkFun Pro Micro RP2040 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 1.6.9 Pico RGB Keypad Base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 1.6.10 Pico Omnibus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 1.6.11 Pimoroni Pico VGA Demo Base . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 1.6.12 Tiny 2040 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Chapter 2 • Raspberry Pi Pico Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.2 Installing MicroPython on Pico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.2.1 Using a Raspberry Pi 4 to help install MicroPython on the Pico . . . . . . . . . . . . . . 27 2.2.2 Using a PC (Windows 10) to help install MicroPython on Pico . . . . . . . . . . . . . . 34 Chapter 3 • Simple Programs – Software Only . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 3.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 3.2 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 3.2.1 Average of two numbers read from the keyboard . . . . . . . . . . . . . . . . . . . . . . . 38 3.2.2 Average of 10 numbers read from the keyboard . . . . . . . . . . . . . . . . . . . . . . . 38 3.2.3 Surface area of a cylinder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3.2.4 ºC to ºF conversion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40

●5

Raspberry Pi Pico for Radio Amateurs 3.2.5 Surface area and volume of a cylinder – user function . . . . . . . . . . . . . . . . . . . 41 3.2.6 Table of squares of numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.2.7 Table of trigonometric sine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 3.2.8 Table of trigonometric sine, cosine and tangent . . . . . . . . . . . . . . . . . . . . . . . . 43 3.2.9 Trigonometric function of a required angle . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 3.2.10 Words in reverse order . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3.2.11 Calculator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 3.2.12 Dice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 3.2.13 Sorting lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 3.2.14 File processing — writing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 3.2.15 File processing — reading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 3.2.16 Squares and cubes of numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 3.2.17 Multiplication timetable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 3.2.18 Odd or even? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 3.2.19 Binary, octal, and hexadecimal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 3.2.20 Add two matrices . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 3.2.21 Shapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 Chapter 4 • Amateur Radio Programs — Software Only . . . . . . . . . . . . . . . . . . . . . 53 4.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 4.2 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 4.2.1 4-band resistor color code identifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 4.2.2 4-band resistor color code identifier including small resistors . . . . . . . . . . . . . . 55 4.2.3 Resistive potential divider . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57 4.2.4 Resistive attenuator design — equal source & load resistances . . . . . . . . . . . . . 59 4.2.5 Resistive attenuator design — unequal source & load resistances . . . . . . . . . . . 63 4.2.6 Zener diode based voltage regulator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 4.2.7 RC circuit frequency response . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69 4.2.8 Resonance in series RLC circuits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 4.2.9 Calculating the inductance of a single-layer coil . . . . . . . . . . . . . . . . . . . . . . . . 74 4.2.10 Constructing a single-layer coil for required inductance . . . . . . . . . . . . . . . . . 76 4.2.11 Bipolar junction transistor (BJT) voltage divider biasing . . . . . . . . . . . . . . . . . 77 4.2.12 Designing a common-emitter BJT transistor amplifier circuit . . . . . . . . . . . . . . 80

●6

 4.2.13 Designing active low-pass filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84 4.2.14 Quarter-wave vertical antenna length . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 4.2.15 The '555' Monostable / bistable / astable chip . . . . . . . . . . . . . . . . . . . . . . . . 90 4.2. Impedance matching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 Chapter 5 • Simple Hardware-Based Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 5.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 5.2 Project 1: Flashing the on-board LED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 5.3 Project 2: External flashing LED . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 5.4 Project 3: Changing the LED flashing rate using pushbutton interrupts . . . . . . . . 104 5.5 Project 4: Binary counting LEDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 5.6 Using parallel LCDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112 5.7 Project 5: LCD functions — displaying text . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 5.8 Project 6: Seconds counter – Parallel LCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 5.9 Using I2C LCDs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 5.10 Project 7: Seconds counter with I2C LCD . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 Chapter 6 • Amateur Radio Hardware-based Projects . . . . . . . . . . . . . . . . . . . . . 125 6.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 6.2 Project 1: Station mains On/Off power control . . . . . . . . . . . . . . . . . . . . . . . . . 125 6.3 Project 2: Station clock . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 6.4 Project 3: Station temperature and humidity . . . . . . . . . . . . . . . . . . . . . . . . . . 134 6.5 Project 4: Station geographical coordinates . . . . . . . . . . . . . . . . . . . . . . . . . . . 137 6.6 Waveform generation – using software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 6.6.1 Project 5: Generating a squarewave signal with amplitude under +3.3 V . . . . . 145 6.6.2 Project 6: Generating fixed voltages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 6.6.3 Project 7: Generating a sawtooth signal . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 6.6.4 Project 8: Generating a triangular-wave signal . . . . . . . . . . . . . . . . . . . . . . . 154 6.6.5 Project 9: Arbitrary periodic waveform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 6.6.6 Project 10: Generating a sinewave signal . . . . . . . . . . . . . . . . . . . . . . . . . . . 158 6.6.7 Project 11: Generating an accurate sinewave signal using timer interrupts . . . . 161 6.7 Waveform generation — using hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163 6.7.1 Project 12: Fixed-frequency waveform generator . . . . . . . . . . . . . . . . . . . . . . 164

●7

Raspberry Pi Pico for Radio Amateurs 6.7.2 Project 13: Generating waveforms with frequency-entry on keypad and LCD readout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 6.8 Project 14: Frequency counter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 6.9 Voltmeter – Ammeter – Ohmmeter – Capacitance meter . . . . . . . . . . . . . . . . . . 187 6.9.1 Project 15: Voltmeter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 6.9.2 Project 16: Ammeter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190 6.9.3 Project 17: Ohmmeter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190 6.9.4 Project 18: Capacitance meter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192 6.10 Project 19: RF power meter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196 6.10.1 RF attenuators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 6.10.2 dB, dBm, and W? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 6.11 Project 20: Using the RadioStation Click board . . . . . . . . . . . . . . . . . . . . . . . . 206 6.12 Morse Code exercisers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 6.12.1 Project 21: Characters entered by the user . . . . . . . . . . . . . . . . . . . . . . . . . 217 6.12.2 Project 22: Sending randomly generated characters . . . . . . . . . . . . . . . . . . . 222 6.12.3 Project 23: Setting Morse speed using an LCD and a rotary encoder . . . . . . . 225 6.13 Project 24: Relay sequencer with time delays . . . . . . . . . . . . . . . . . . . . . . . . . 232 6.14 Project 25: FM radio with the Raspberry Pi Pico . . . . . . . . . . . . . . . . . . . . . . . 236 6.14.1 Project 26: Modified FM Radio - increasing the output signal level – connecting a loudspeaker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244 6.14.2 Project 27: FM radio using an LCD and external buttons . . . . . . . . . . . . . . . . 246 6.14.3 Project 28: FM radio using an LCD and rotary encoder . . . . . . . . . . . . . . . . . 251 6.15 Project 29: Measure the frequency and duty cycle of a PWM waveform – screen display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 6.16 Project 30: Measure the frequency and duty cycle of a PWM waveform – LCD display . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259 6.17 Raspberry Pi Pico Bluetooth interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260 6.17.1 Project 31: Controlling an LED from a smartphone using Bluetooth . . . . . . . . 260 6.18 Project 32: Station security . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 265 6.19 Project 33: Generating accurate squarewave signals using the Raspberry Pi Pico State Machines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270 6.20 Project 34: Using Wi-Fi with the Raspberry Pi Pico – Controlling an LED from a smartphone . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 271

●8

 6.21 Project 35: Audio amplifier module with rotary encoder volume control . . . . . . . 279 6.22 Project 36: Morse decoder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 285 6.23 Raspberry Pi Pico RTL-SDR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 296 6.24 Project 37: Using the FS1000A 433 MHz transmitter/receiver pair . . . . . . . . . . 298 Chapter 7 • Running a Program Automatically after the Raspberry Pi Pico Boots . 304 APPENDIX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306 Parts Used in Projects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 306 Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 307

●9

Raspberry Pi Pico for Radio Amateurs

● 10

Preface

Preface In recent years, there have been major changes in the equipment typically used by radio amateurs. Although much classical HF and mobile equipment is still in use by a large number of amateurs, we see the use of computers and digital techniques gaining popularity among amateur radio operators or 'hams'. In the early days of digital communications, personal computers were used by radio amateurs to communicate with each other. Sadly, these PCs have the disadvantage of being rather expensive and bulky. Today though, anyone can buy a 5-euros Raspberry Pi Pico computer and build many interesting amateur radio projects using this device which is smaller than a credit card. Several authors have produced books and published projects for implementing the Arduino and the Raspberry Pi in amateur radio projects. The Raspberry Pi Pico is a practical alternative to the Arduino because of its low cost, speed, processing power, large memory, many input-output ports, peripheral hardware support, and easy programming. The Raspberry Pi Pico has no operating system, and this makes it easy to use as a general-purpose microcontroller. As a result of these features, the RPi Pico is well suited for use as a "drop-in" computer for amateur radio projects. This book has three purposes: firstly, it is aimed to teach the basic operating principles and features of the Raspberry Pi Pico to beginners. Secondly, software-only projects are presented that will be of interest to amateur radio operators. Lastly, many hardware-based projects are given using the Raspberry Pi Pico in conjunction with the Python 3 programming language. Although these projects are broad-spectrum in nature, they have been chosen to be interesting and useful to the amateur radio operators. All the projects used in the book have been assessed and are fully working. The projects are described by giving their block diagrams, circuit diagrams, and full program listings. The program listings are described in detail and readers should find it easy to modify the projects for their own requirements. The programs discussed in this book are available from the support and resources web page created for the book at the Elektor Store website www.elektor.com. There, the page can be found by searching for "Raspberry Pi Pico for Radio Amateurs". The .zip archive file is under "Downloads". The programs can easily be downloaded, extracted, and stored locally to save the time and effort of typing them. I hope you enjoy reading the book and find the projects interesting and useful. Prof Dogan Ibrahim, G7SCU London, 2021

● 11

Raspberry Pi Pico for Radio Amateurs

Chapter 1 • Raspberry Pi Pico Hardware 1.1 Overview Raspberry Pi Pico is a single-board microcontroller module developed by the Raspberry Pi Foundation. The module is based on the RP2040 microcontroller chip. In this Chapter we will be looking at the hardware details of the Raspberry Pi Pico microcontroller module in some detail. From now on, we will be calling this microcontroller module "Pico" for short.

1.2 Pico hardware module Pico is a very low-cost, $4 microcontroller module based on the RP2040 microcontroller chip with dual Cortex-M0+ processor. Figure 1.1 shows the front view of the Pico hardware module which is a small board. At the middle of the board is the tiny 7 × 7 mm RP2040 microcontroller chip housed in a QFN-56 package. At the two edges of the board there are forty gold-colored metal GPIO (General Input Output) pins with holes. You should solder pins to these holes so that external connections can be made easily to the board. The holes are marked starting with number 1 at the top left corner of the board and the numbers increase downwards up to number 40 which is at the top right hand corner of the board. The board is breadboard compatible (i.e., 0.1-inch pin spacing), and after soldering the pins, the board can be plugged on a breadboard for easy connection to the GPIO pins using jumper wires. Next to these holes you will see bumpy circular cut-outs which can be plugged-in on top of other modules without having any physical pins fitted.

Figure 1.1: Front view of the Pico hardware module. At one edge of the board there is the micro-USB B port for providing power to the board and for programming the board. Next to the USB port sits an on-board user LED that can be used during program development. Next to this LED there is a button named as BOOTSEL which is used during programming of the microcontroller as we will see in next Chapters. At the other edge of the board, next to the Raspberry Pi logo, there are three connectors that are used to debug your programs. Figure 1.2 shows the back view of the Pico hardware module. Here, all the GPIO pins are identified with letters and numbers. You will notice the following types of letters and numbers:

● 12

Chapter 1 • Raspberry Pi Pico Hardware

GND AGND 3V3 GP0 – GP22 GP26_A0 – GP28_A2 ADC_VREF TP1 – TP6 SWDIO, GND, SWCLK RUN

3V3_EN VSYS VBUS

— power supply ground (digital ground) — power supply ground (analog ground) — +3.3 V power supply (output) — digital GPIO — analog inputs — ADC reference voltage — test points — debug interface — default RUN pin. Connect LOW to reset the RP2040

— this pin by default enables the +3.3 V power supply. +3.3 V can be disabled by connecting this pin LOW — system input voltage (1.8 V to 5.5 V) used by the on-board SMPS to generate +3.3 V supply for the board — micro-USB input voltage (+5 V)

Figure 1.2: Back view of the Pico hardware module. Some of the GPIO pins are used for internal board functions. These are: GP29 GP25 GP24 GP23

(input) (output) (input) (output)

— — — —

used in ADC mode (ADC3) to measure VSYS/3 connected to on-board user LED VBUS sense HIGH if VBUS is present, else LOW Controls the on-board SMPS Power Save pin

The specifications of the Pico hardware module are as follows: • 32-bit RP2040 Cortex-M0+ dual core processor operating at 133 MHz • 2 MByte Q-SPI Flash memory • 264 Kbyte SRAM memory • 26 GPIO (+3.3 V compatible) • 3 × 12-bit ADC pins • Serial Wire Debug (SWD) port • Micro-USB port (USB 1.1) for power (+5 V) and data (programming) • 2 × UART, 2 x I2C, 2 x SPI bus interface • 16 × PWM channels

● 13

Raspberry Pi Pico for Radio Amateurs

• 1 × Timer (with 4 alarms), 1 x Real Time Counter • On-board temperature sensor • On-board LED (on port GP25) • MicroPython, C, C++ programming • Drag & drop programming using mass storage over USB The Pico's GPIO hardware is +3.3 V compatible, and it is therefore important to be careful not to exceed this voltage when interfacing external devices to the GPIO pins. +5 V to +3.3 V logic converter circuits or resistive potential divider circuits must be used if it is required to interface devices with +5 V outputs to the Pico GPIO pins. Figure 1.3 shows a resistive potential divider circuit that can be used to lower +5 V to +3.3 V. A logic level converter module is shown in Figure 1.4. This module can be used to interface the Pico pins to +5 V devices. Connect GND pins to ground, and HV and LV pins to +5 V and +3.3 V, respectively. Use TXI-TXO pins co connect the +3.3 V Pico outputs to +5 V input devices. Similarly, use RXI-RXO pins to connect +5 V output devices to +3.3 V Pico input pins.

Figure 1.3: Resistive potential divider circuit.

Figure 1.4: Logic converter module.

1.3 Comparison with the Arduino UNO The Arduino UNO is one of the most popular microcontroller development boards used by students, practicing engineers, and hobbyists. Both the Arduino UNO and Raspberry Pi Pico module are microcontrollers with no operating systems. Table 1.1 shows a comparison of

● 14

Chapter 1 • Raspberry Pi Pico Hardware

the Raspberry Pi Pico with the Arduino UNO. It is clear from this table that the Pico is much faster than the Arduino UNO, has larger flash and data memories, provides more digital input-output pins, and has an on-board temperature sensor. The Arduino UNO operates at +5 V and its GPIO pins are +5 V compatible. Some advantages of the Arduino UNO include its built-in EEPROM memory and its ADC with six channels instead of three as in the Pico. Feature

Raspberry Pi Pico

Arduino UNO

Microcontroller

RP2040

Atmega328P

Core and bits

Dual core, 32-bits, Cortex-M0+

Single-core 8-bits

RAM

264 Kbyte

2 KByte

Flash

2 MByte

32 KByte

CPU speed

48 MHZ to 133 MHz

16 MHz

EEPROM

None

1 KByte

Power input

+5 V through USB port

+5 V through USB port

Alternative power

2–5 V via VSYS pin

7–12 V

MCU operating voltage

+3.3 V

+5 V

GPIO count

26

20

ADC count

3

6

Hardware UART

2

1

Hardware I2C

2

1

Hardware SPI

2

1

Hardware PWM

16

6

Programming

MicroPython, C, C++

C (Arduino IDE)

On-board LED

1

1

Cost

$4

$20

languages

Table 1.1: Comparison of Raspberry Pi Pico and Arduino UNO.

1.4 Operating conditions and powering the Pico The recommended operating conditions of the Pico are: • Operating temperature: –20 ºC to +85 ºC • VBUS voltage: +5 V ±10% • VSYS voltage: +1.8 V to +5.5 V An on-board SMPS is used to generate the +3.3 V to power the RP2040 from a range of input voltages from 1.8 V to +5.5 V. For example, three alkaline AA batteries can be used to provide +4.5 V to power Pico.

● 15

Raspberry Pi Pico for Radio Amateurs

Pico can be powered in several ways. The simplest method is to plug the micro-USB port to a +5 V power source, such as the USB port of a computer or a +5 V power adapter. This will provide power to the VSYS input (see Figure 1.5) through a Schottky diode. The voltage at the VSYS input is therefore VBUS voltage minus the voltage drop of the Schottky diode (about +0.7 V). VBUS and VSYS pins can be shorted if the board is powered from an external +5 V USB port. This will increase the voltage input slightly and hence reduce ripples on VSYS. VSYS voltage is fed to the SMPS through the RT6150 which generates a fixed +3.3 V supply for the MCU and other parts of the board. VSYS is divided by three and is available at analog input port GPIO29 (ADC3), which can easily be monitored. GPIO24 checks the existence of VBUS voltage and is at logic HIGH if VBUS is present. Another method to power the Pico is by applying an external voltage (+1.8 V to +5.5 V) to the VSYS input directly (e.g., using batteries or external power supply). We can also use the USB input and VSYS inputs together to supply power to Pico, for example, to allow operation from both batteries and the USB port. If this method is used, then a Schottky diode should be used at the VSYS input to prevent the supplies from interfering with each other. The higher of the voltages will power VSYS.

Figure 1.5: Powering the Pico.

1.5 Pinout of the RP2040 microcontroller and Pico module Figure 1.6 shows the RP2040 microcontroller pinout, which is housed in a 56-pin package. The Pico module pinout is shown in Figure 1.7 in detail. As you can see from the figure, most pins have multiple functions. For example, GPIO0 (pin 1) is also the UART0 TX, I2C0 SDA, and the SPI0 RX pins.

● 16

Chapter 1 • Raspberry Pi Pico Hardware

Figure 1.6: RP2040 microcontroller pinout.

Figure 1.7: Pico pinout.

● 17

Raspberry Pi Pico for Radio Amateurs

Figure 1.8 shows a simplified block diagram of the Pico hardware module. Notice that the GPIO pins are directly connected from the microcontroller chip to the GPIO connector. GPIO numbers 26, 27, 28 can be used either as digital GPIO or as ADC inputs. ADC inputs GPIO26-29 have reverse polarity diodes to 3 Vs and therefore the input voltage must not exceed 3V3 + 300 mV. Another point to note is that if the RP2040 is not powered, applying voltages to GPIO26-29 pins may leak through the diode to the power supply. There is no problem with the other GPIO pins, and voltage can be applied safely when the RP2040 is not powered.

Figure 1.8: Simplified block diagram.

1.6 Other RP2040 microcontroller-based boards While authoring this book, some third-party manufacturers have been developing microcontrollers based on the RP2040 chip. Some examples are given in this section.

1.6.1 Adafruit Feather RP2040 This microcontroller board (Figure 1.9) has the following basic specifications: • RP2040 32-bit Cortex-M0+ running at 125MHz • 4 MB Flash memory • 264 KB RAM • 4 × 12-bit ADC • 2 × I2C, 2 × SPI, 2 × UART • 16 × PWM • 200 mA LiPo charger • Reset and Bootloader buttons • 24 MHz crystal • +3.3 V regulator with 500 mA current output • USB type C connector • On-board red LED • RGB NeoPixel • On-board STEMMA QT connector with optional SWD debug port

● 18

Chapter 1 • Raspberry Pi Pico Hardware

Figure 1.9: Adafruit Feather RP2040.

1.6.2 Adafruit ItsyBitsy RP2040 The ItsyBitsy RP2040 (Figure 1.10) is another RP2040-based microcontroller board from Adafruit. Its basic features are similar to Feather RP2040. It has a USB-micro B connector and provides +5 V output.

Figure 1.10: Adafruit ItsyBitsy RP2040.

1.6.3 Pimoroni PicoSystem This is a mini gaming board (Figure 1.11) developed around the RP2040 microcontroller. Its basic features are: • 133 MHz clock • 264 KB SRAM • LCD screen • Joypad • Buttons • LiPo battery • USB-C power connector

● 19

Raspberry Pi Pico for Radio Amateurs

Figure 1.11: Pimoroni PicoSystem.

1.6.4 Arduino Nano RP2040 Connect This board (Figure 1.12) offers 16 MB flash, a 9-axis IMU, a microphone, plus a very efficient power section equipped with Wi-Fi/Bluetooth. It includes a u-blox NINA-W102 radio module to make the unit IoT compatible. A built-in microphone (MP34DT05) is available for sound activation, audio control, and even AI voice recognition. The 6-axis smart IMU (LSM6DSOXTR) with AI capabilities tells the board which way it is moving and adds fall sensing and double-tap activation. It includes full Wi-Fi 802.11b/g/n connectivity, along with Bluetooth® and BLE v4.2. Supports the Arduino programming language, the IDE 2.0 and all the associated libraries.

Figure 1.12: Arduino Nano RP2040 Connect.

● 20

Chapter 1 • Raspberry Pi Pico Hardware

1.6.5 SparkFun Thing Plus RP2040 This development platform (Figure 1.13) provides an SD card slot, 16MB flash memory, a JST single cell battery connector, a WS2812 RGB LED, JTAG pins, and Qwiic connector. Its basic features are: • 133 MHz speed • 264 KB SRAM • 4 × 12-bit ADC • 2 × UART, 2 × I2C, 2 × SPI • 16 × PWM • 1 × timer with 4 alarms

Figure 1.13: SparkFun Thing Plus RP2040.

1.6.6 Pimoroni Pico Explorer Base This development board (Figure 1.14) includes a small breadboard and a 240 × 240 IPS LCD display with four tactile buttons. A socket is provided on the board to plug-in a Raspberry Pi Pico board. The basic features of this development board are: • Piezo speaker • 1.54 inch IPS LCD • 4 × buttons • 2 × half-bridge motor drives • Two breakout I2C sockets • Easy access to GPIO and ADC pins • Mini breadboard • No soldering required • Raspberry Pi Pico not supplied

● 21

Raspberry Pi Pico for Radio Amateurs

Figure 1.14: Pimoroni Pico Explorer Base.

1.6.7 SparkFun MicroMod RP2040 Processor This board (Figure 1.15) includes a MicroMod M.2 connector for access to the GPIO pins.

Figure 1.15: SparkFun MicroMod RP 2040 Processor.

1.6.8 SparkFun Pro Micro RP2040 This board (Figure 1.16) includes an ES2812B addressable LED, a boot button, a reset button, a Qwiic connector, a USB-C power interface, a PTC fuse, and castellated GPIO pads.

● 22

Chapter 1 • Raspberry Pi Pico Hardware

Figure 1.16: SparkFun Pro Micro RP2040.

1.6.9 Pico RGB Keypad Base This board is equipped with 4 × 4 rainbow-illuminated keypad (Figure 1.17) with APA102 LEDs. The basic features are: • 4 × 4 keypad • 16 x APA102 RGB LEDs • Keypad connected via I2C I/O expander • labelled GPIO pins

Figure 1.17: Pico RGB Keypad Base.

1.6.10 Pico Omnibus This is an expansion board for the Pico (Figure 1.18). Basic features of this board are: • labelled GPIO pins • Two landing areas with labelled (mirrored) male headers for attaching add-ons. • 4 × rubber feet • Compatible with Raspberry Pi Pico. • Fully assembled. • Dimensions: approx. 94 × 52 mm × 12 mm

● 23

Raspberry Pi Pico for Radio Amateurs

Figure 1.18: Pico Omnibus.

1.6.11 Pimoroni Pico VGA Demo Base This board (Figure 1.19) has VGA output and an SD card slot. The basic features are: • Powered by Raspberry Pi Pico • 15-pin VGA connector • I2S DAC for line out audio • PWM audio output • SD card slot • Reset button • Headers to install your Raspberry Pi Pico • Three user switches • No soldering required

● 24

Chapter 1 • Raspberry Pi Pico Hardware

Figure 1.19: Pimoroni Pico VGA Demo Base.

1.6.12 Tiny 2040 This board (Figure 1.20) is a postage stamp sized RP2040 development board with a USB-C connection and 8 MB of flash. The board features: • 264 KB SRAM • USB-C connector for power, programming, and data transfer • 8 MB QSPI flash supporting XiP • User controllable RGB LED • 12 IO pins (including four 12-bit ADC channels) • Switch for basic input (doubles up as DFU select on boot) • On-board 3V3 regulator (max output current 300mA) • Input voltage range 3 V to 5.5 V • Dimensions: approx. 22.9 ×18.2 × 6mm (L x W x H, including the USB-C port)

● 25

Raspberry Pi Pico for Radio Amateurs

Figure 1.20: Tiny 2040

● 26

Chapter 2 • Raspberry Pi Pico Programming

Chapter 2 • Raspberry Pi Pico Programming 2.1 Overview At the time of authoring this book, the Raspberry Pi Pico could be programmed using the following programming languages: • C/C++ • MicroPython • Assembly language Although the Pico by default is set up for use with the powerful and popular C/C++ language, many beginners find it easier to use MicroPython, which is a version of the Python programming language developed specifically for microcontrollers. In this Chapter we will learn how to install and use the MicroPython programming language. We will be using the Thonny text editor which has been developed specifically for Python programs. Many working and fully tested projects will be given in the next Chapters using MicroPython with our Pico.

2.2 Installing MicroPython on Pico MicroPython must be installed on the Pico before it can be used. Once it is installed it stays on your Pico unless it is overwritten with something else. Installing MicroPython requires an Internet connection, although only once. Since the Pico has no Wi-Fi connectivity, we will need to use a computer with Internet access. This can be done either by using a Raspberry Pi (e.g., a Raspberry Pi 4), or by using a PC. In this section we will see how to do the installation using both methods.

2.2.1 Using a Raspberry Pi 4 to help install MicroPython on the Pico The steps are as follows: • Boot your Raspberry Pi 4 and login to Desktop. • Make sure your Raspberry Pi is connected to the Internet. • Hold down the BOOTSEL button on your Pico. • Connect your Pico to one of the USB ports of the Raspberry Pi 4 using a micro-USB cable while holding down the button. • Wait a few seconds and let go the BOOTSEL button. • You should see the Pico appear as a removable drive. Click OK in the Removable medium is inserted window (Figure 2.1).

● 27

Raspberry Pi Pico for Radio Amateurs

Figure 2.1: Click OK. • In the File Manager window, you will see two files with the names INDEX.HTM and INFO_UF2.TXT (see Figure 2.2).

Figure 2.2: You will see two files. • Double click on file INDEX.HTM and scroll down. • You should see the message Raspberry Pi Documentation displayed in a web page (Figure 2.3).

● 28

Chapter 2 • Raspberry Pi Pico Programming

Figure 2.3: Displayed message. • Scroll down and click on the MicroPython tab and then click Download UF2 file to download the MicroPython firmware (Figure 2.4). You should see the downloaded file message at the bottom of the screen (Figure 2.5).

Figure 2.4: Download UF2 file.

● 29

Raspberry Pi Pico for Radio Amateurs

Figure 2.5: Downloaded message. • Close your browser window by clicking on the cross icon located at the top right corner. • Open the File Manager by clicking on menu, followed by Accessories. • Open the Downloads folder (under /home/pi) and locate the file with the extension: .uf2. This file will have the name similar to: rp2-pico-20210902-v1.17.uf2 (Figure 2.6).

Figure 2.6: Locate file with extension: .uf2. • Drag and drop this file onto the Raspberry Pi Pico's removable drive called: RPI-RP2 (at the top left side of the screen – see Figure 2.6). • After a while, the MicroPython firmware will be installed onto the internal storage of the Pico and the drive will disappear. Close the window. • Your Pico is now running MicroPython. • Powering down the Pico will not remove MicroPython from its memory. Using the Thonny text editor from Raspberry Pi Thonny is a free Python Integrated Development Environment (IDE) developed specifically for Python. It has built-in text editor and debugger and a number of other utilities that can be useful during program development.

● 30

Chapter 2 • Raspberry Pi Pico Programming

In this section we will learn how to use the Thonny by invoking it from the Raspberry Pi. You should leave your Pico connected to the Raspberry Pi. We will create a one-line program to display the message Hello from Raspberry Pi Pico: The steps are: • Click menu, followed by Programming on your Raspberry Pi Desktop and then click Thonny Python IDE (see Figure 2.7). The author had version 3.7.3 of Thonny installed on his Raspberry Pi 4.

Figure 2.7: Start Thonny on your Raspberry Pi. • Click on the label Python at the bottom right hand corner of Thonny (Figure 2.8).

Figure 2.8: Click "Python" in the bottom right-hand corner. • Click to select MicroPython (Raspberry Pi Pico) as shown in Figure 2.9.

Figure 2.9: Select Raspberry Pi Pico.

● 31

Raspberry Pi Pico for Radio Amateurs

• You should see the version number of your MicroPython displayed in the bottom part of the screen where the Shell resides (Figure 2.10).

Figure 2.10: Version number of MicroPython is displayed. • We are now ready to write our simple program. Enter the following line in the lower part of the screen where Shell is visible. Program statements written in this part of Thonny are executed online and immediately. This part is normally used to evaluate parts of a program. Enter: print("Hello from Raspberry Pi Pico")

and you should see the message Hello from Raspberry Pi Pico displayed, as shown in Figure 2.11.

Figure 2.11: Displaying a message. Icons of the Thonny At the top of the Thonny screen, you will see a number of icons as shown in Figure 2.12. The functions of these icons are described in this section (notice that letters are used to identify the icons).

Figure 2.12: Thonny icons. A: NEW. B: Open. C: Save. D: Run. E: Debug. F: Step Over. G: Step Into. H: Step Out. I: Resume. J: Stop/Restart.

● 32

This icon is used to create a new file. This icon is used to Open an existing file This icon is used to Save a file This option is used to run the current program This icon is used to debug the current program This option is used to step over a function when in Debug mode This option is used to step into a function in Debug mode This icon is used to step out of a function in Debug mode This option is used to resume a stopped session This option is used to stop/restart a session

Chapter 2 • Raspberry Pi Pico Programming

Writing a program using Thonny In an earlier section we saw how to execute a statement online using the Thonny Shell. Virtually all applications require programs to be written. As an example, the steps to write and run a quite simple one-line program to display the message Hello from program… are given below. • Enter the program statements at the upper part of the screen as shown in Figure 2.13.

Figure 2.13: Write the program at upper part of the screen. • Click File followed by Save As and give a name to your program. e.g., FirstProg. You have the option of storing the program either on your Raspberry Pi or on the Pico. Click Raspberry Pi Pico to save it on the Pico (Figure 2.14). Enter the name of your program (FirstProg) and click OK (notice that the file is saved with the extension .py).

Figure 2.14: Click Raspberry Pi Pico to save your program. • Click the green arrow icon at the top of the screen (under Run) to run your program. The output of the program will be displayed in the lower Shell part of the screen as shown in Figure 2.15.

Figure 2.15: Output of the program.

● 33

Raspberry Pi Pico for Radio Amateurs

2.2.2 Using a PC (Windows 10) to help install MicroPython on Pico In Section 2.2.1 we learned how to install MicroPython on Pico using a Raspberry Pi 4. In this section we will see how to install MicroPython using only a PC running the Windows 10 operating system. This is the option you should choose if you do not have access to a Raspberry Pi. The steps are as follows. • Make sure your PC is connected to the Internet. • Hold down the BOOTSEL button on your Pico. • Connect your Pico to the USB port of your PC using a micro-USB cable while holding down the button. • Wait a few seconds and let go the BOOTSEL button. • You should see the Pico appear as a removable drive with the name RPI-RP2 as shown in Figure 2.16 (drive E: in this case).

Figure 2.16: Pico as a removable drive RPI-RP2. • Click on drive RPI-RP2. You will see two files with the names INDEX.HTM and INFO_UF2.TXT (see Figure 2.17).

Figure 2.17: You will see two files. • Double click on file INDEX.HTM and scroll down. • You should see the message Raspberry Pi Documentation displayed in a web page (Figure 2.3).

● 34

Chapter 2 • Raspberry Pi Pico Programming

• Scroll down and click on the MicroPython tab and then click Download UF2 file to download the MicroPython firmware (Figure 2.4). You should see the downloaded file in your Downloads folder (Figure 2.18). This file will have the name similar to: rp2-pico-20210902-v1.17.uf2.

Figure 2.18: Downloaded file. • Open the Downloads folder and locate the file with the extension: .uf2. • Drag and drop this file to Raspberry Pi Pico's removable drive named: RPI-RP2. • After a while, the MicroPython firmware will be installed onto the internal storage of Pico and the drive RPI-RP2 will disappear. • Your Pico is now running MicroPython. • Powering down the Pico will not remove MicroPython from its memory. Using the Thonny text editor from the PC In the previous section we learned how to use the Thonny on Raspberry Pi and develop, save, and run programs on the Pico. In this section we will be using Thonny on the PC so that a Raspberry Pi is not needed to develop and run our programs. First of all, we have to install Thonny on our PC (if it is not already installed). The steps are: • Go to the Thonny.org web site: https://thonny.org/ • Click on the link at the top right-hand side of the screen to install Thonny (see Figure 2.19)

Figure 2.19: Click to install Thonny. • You should see an icon on the Desktop (Figure 2.20) of your PC. Double-click to start Thonny.

● 35

Raspberry Pi Pico for Radio Amateurs

Figure 2.20: Thonny icon on the Desktop. • The startup screen of Thonny on your PC is shown in Figure 2.21.

Figure 2.21: Thonny startup screen on the PC. • Click on the label Python at the bottom right-hand corner of the screen and click to select MicroPython (Raspberry Pi Pico) • You are now ready to write your programs. • Enter the following statement at the lower part of the screen (in Shell): • print("hello from Thonny on PC") • You should the message "hello from Thonny on PC" is displayed as shown in Figure 2.22.

● 36

Chapter 2 • Raspberry Pi Pico Programming

Figure 2.22: Displaying the message. In this book we will be using the Thonny on the PC to write programs and to execute them on the Raspberry Pi Pico.

● 37

Raspberry Pi Pico for Radio Amateurs

Chapter 3 • Simple Programs – Software Only 3.1 Overview Simple example programs are given in this Chapter to make the reader familiar with programming the Raspberry Pi Pico using the Python language. The aim here has been to review the basic Python programming concepts. This book does not aim to teach Python programming, and fortunately, there are many publications and tutorials on the Internet for that purpose.

3.2 Examples 3.2.1 Average of two numbers read from the keyboard In this example, two numbers are read from the keyboard and their average is displayed. The aim of this example is to show how data can be read from the keyboard. Solution The program is named Average and the program listing and an example run of the program are shown in Figure 3.1. Function input is used to read the numbers in the form of strings from the keyboard. These strings are then converted into floating point-numbers and stored in variables n1 and n2. The average is calculated by adding and then dividing the numbers by two. The result is displayed on the screen.

Figure 3.1: Program: Average and sample run.

3.2.2 Average of 10 numbers read from the keyboard In this example, 10 numbers are read from the keyboard and their average is displayed. The aim of this example is to show how a loop can be constructed in Python.

● 38

Chapter 3 • Simple Programs – Software Only

Solution The program is named Average10 and the program listing, and an example run of the program are shown in Figure 3.2. In this program a loop is constructed which runs from 0 to 9 (i.e., 10 times). Inside this loop the numbers are read from the keyboard, added to each other, and stored in variable sum. The average is then calculated and displayed by dividing sum by 10. Notice that a new-line is not printed after the print statements since the option end = ' ' is used inside the print statement.

Figure 3.2: Program: Average10 and sample run.

3.2.3 Surface area of a cylinder In this example the radius and height of a cylinder are read from the keyboard and its surface area is displayed on the screen. Solution The program is named CylArea and the program listing, and an example run of the program are shown in Figure 3.3. The surface area of a cylinder is given by: Surface area = 2 × π × r × h Where r and h are the radius and height of the cylinder, respectively. In this program the math library is imported so that function Pi can be used in the program. The surface area of the cylinder is displayed after reading its radius and height.

● 39

Raspberry Pi Pico for Radio Amateurs

Figure 3.3: Program: CylArea and sample run.

3.2.4 ºC to ºF conversion In this example the program reads degrees Celsius from the keyboard and converts and displays the equivalent degrees Fahrenheit. Solution The program is named CtoF and the program listing, and an example run of the program are shown in Figure 3.4. The formula to convert ºC to ºF is: F = 1.8 × C + 32

Figure 3.4: Program: CtoF and sample run.

● 40

Chapter 3 • Simple Programs – Software Only

3.2.5 Surface area and volume of a cylinder – user function In this example, the surface area and volume of a cylinder are calculated whose radius and height are given. The program uses a function to calculate and return the surface area and the volume. Solution The program is named CylAreaSurf and the program listing, and an example run of the program are shown in Figure 3.5. The surface area and the volume of a cylinder are given by: Surface area = 2 × π × r × h Volume = π × r2 × h Where r and h are the radius and height of the cylinder, respectively. Function Calc is used to get the radius and height of the cylinder. The function returns the surface area and volume to the main program which are displayed on the screen.

Figure 3.5: Program CylAreaSurf and sample run.

3.2.6 Table of squares of numbers In this example the squares of numbers from 1 to 11 are calculated and tabulated. Solution The program is named Squares and the program listing and an example run of the program are shown in Figure 3.6. Notice that \t prints a tab so that the data can be tabulated nicely.

● 41

Raspberry Pi Pico for Radio Amateurs

Figure 3.6: Program: Squares and sample run.

3.2.7 Table of trigonometric sine In this example the trigonometric sine is tabulated from 0 to 45 degrees in steps of 5 degrees. Solution The program is named Sines and the program listing and an example run of the program are shown in Figure 3.7. It is important to notice that the arguments of the trigonometric functions must be in radians and not in degrees.

Figure 3.7: Program: Sines and sample output.

● 42

Chapter 3 • Simple Programs – Software Only

3.2.8 Table of trigonometric sine, cosine and tangent In this example the trigonometric sine, cosine, and tangent are tabulated from 0 to 45 degrees in steps of 5 degrees. Solution The program is named Trig and the program listing, plus an example run of the program are shown in Figure 3.8.

Figure 3.8: Program: Trig and sample output.

3.2.9 Trigonometric function of a required angle In this example, an angle is read from the keyboard. Also, the user specifies whether the sine (s), cosine (c), or the tangent (t) of the angle is required. Solution The program is named TrigUser and the program listing, plus an example run of the program are shown in Figure 3.9.

● 43

Raspberry Pi Pico for Radio Amateurs

Figure 3.9: Program: TrigUser and sample output.

3.2.10 Words in reverse order Write a program to read a word from the keyboard and then display the letters of this word in reverse order on the screen. Solution The required program listing is shown in Figure 3.10 (program: Letters). A word is read from the keyboard and stored in string variable word. Then the letters of this word are displayed in reverse-order. An example run of the program is shown in Figure 3.10.

Figure 3.10: Program: Letters and a sample output.

● 44

Chapter 3 • Simple Programs – Software Only

3.2.11 Calculator Write a calculator program to conduct the four simple mathematical operations of addition, subtraction, multiplication, and division on two numbers received from the keyboard. Solution The required program listing is shown in Figure 3.11 (program: Calc). Two numbers are received from the keyboard and stored in variables n1 and n2. Then, the required mathematical operation is received, and it is performed. The result, stored in variable result, is displayed on the screen. The user is given the option of terminating the program. any = 'y' while any == 'y': print("\nCalculator Program") print("==================") n1 = float(input("Enter first number: ")) n2 = float(input("Enter second number: ")) op = input("Enter operation (+-*/): ") if op =="+": result = n1 + n2 elif op == "-": result = n1 - n2 elif op == "*": result = n1 * n2 elif op == "/": result = n1 / n2 print("Result = %f" %(result)) any = input("\nAny more (yn): ")

Figure 3.11: Program: Calc. An example run of the program is shown in Figure 3.12.

● 45

Raspberry Pi Pico for Radio Amateurs

Figure 3.12: Example run of the program.

3.2.12 Dice Write a program to simulate double dice, i.e., to display two random numbers between 1 and 6 every time it is run. Solution The required program listing is shown in Figure 3.13 (program: Dice). Here, the random number generator randint is used to generate random numbers between 1 and 6 when the Enter key is pressed. The program is terminated when letter x (or X) is entered.

Figure 3.13: Program: Dice. An example run of the program is shown in Figure 3.13.

● 46

Chapter 3 • Simple Programs – Software Only

3.2.13 Sorting lists A list of 5 countries is stored in a list. Write a program to sort the names of these countries in alphabetical order and then display them. Solution The program is named Sort, and its listing and an example run are shown in Figure 3.14. MyList = ['italy', 'france', 'germany', 'india', 'china'] MyList.sort() print("Sorted list : ", MyList)

Figure 3.14: Program: Sort and example output.

3.2.14 File processing — writing In this example, a text file called MyFile.txt will be created and the text Hello from Raspberry Pi Pico! will be written to this file. Solution The program is named Filew, and its listing and an example run are shown in Figure 3.15. The fie is opened in write (w) mode and the text is written in it using function write. Notice here that fp is the file handle.

Figure 3.15: Program: Filew.

3.2.15 File processing — reading In this example the text file MyFile.txt created in the previous example is opened and its contents is displayed on the screen. Solution The program is named Filer, and its listing and an example run are shown in Figure 3.16. The fie is opened in read (r) mode and its contents is displayed.

● 47

Raspberry Pi Pico for Radio Amateurs

Figure 3.16: Program: Filer.

3.2.16 Squares and cubes of numbers Write a program to tabulate the squares and cubes of numbers from 1 to 10. Solution The program is named Cubes, and its listing and an example run are shown in Figure 3.17.

Figure 3.17: Program: Cubes and example output.

3.2.17 Multiplication timetable Write a program to read a number from the keyboard and then display the timetable for this number from 1 to 12. Solution The program is named Times, and its listing and an example run are shown in Figure 3.18.

● 48

Chapter 3 • Simple Programs – Software Only

Figure 3.18: Program: Times and example output.

3.2.18 Odd or even? Write a program to read a number from the keyboard and check and display if this number is odd or even. Solution The program is named OddEven, and its listing and an example run are shown in Figure 3.19.

Figure 3.19: Program: OddEven and example output.

3.2.19 Binary, octal, and hexadecimal Write a program to read a decimal number from the keyboard. Convert this number into binary, octal, and hexadecimal and display on the screen. Solution The program is named Conv, and its listing and an example run are shown in Figure 3.20.

● 49

Raspberry Pi Pico for Radio Amateurs

Figure 3.20: Program: Conv and example output.

3.2.20 Add two matrices Write a program to add two given matrices and display the elements of the new matrix. Solution The program is named AddMatrix, and its listing and an example run are shown in Figure 3.21.

Figure 3.21: Program: AddMatrix and example output.

3.2.21 Shapes Write a program to use functions to calculate and display the areas of shapes: square, rectangle, triangle, circle, and cylinder. The sizes of the required sides should be received from the keyboard.

● 50

Chapter 3 • Simple Programs – Software Only

Solution The areas of the shapes to be used in the program are as follows: Square: side = a Rectangle: sides a, b Circle: radius r Triangle: base b, height h Cylinder: radius r, height h



area area area area area

= = = = =

a2 ab πr2 bh/2 2πrh

The required program listing is shown in Figure 3.22 (program: areas.py). a different function is used for each shape and the sizes of the sides are received inside the functions. The main program displays the calculated area for the chosen shape. #---------------------------------------------#



AREAS OF SHAPES

#



===============

# # This program calculates and displays the areas # of various geometrical shapes # of numbers in a list # # Author: Dogan Ibrahim # File

: areas.py

# Date

: August, 2021

#---------------------------------------------import math def Square(a):



# square

return a * a def Rectangle(a, b):

# rectangle

return(a * b) def Triangle(b, h):

# triangle

return(b * h / 2) def Circle(r):

# circle

return(math.pi * r * r) def Cylinder(r, h):

# cylinder

return(2 * math.pi * r * h) print("AREAS OF SHAPES") print("===============\n") print("What is the shape?: ")

● 51

Raspberry Pi Pico for Radio Amateurs

shape = input("Square (s)\nRectangle(r)\nCircle(c)\n\ Triangle(t)\nCylinder(y): ") shape = shape.lower() if shape == 's': a = float(input("Enter a side of the square: ")) area = Square(a) s = "Square" elif shape == 'r': a = float(input("Enter one side of the rectangle: ")) b = float(input("Enter other side of the rectangle: ")) area = Rectangle(a, b) s = "Rectangle" elif shape == 'c': radius = float(input("Enter radius of the circle: ")) area = Circle(radius) s = "Circle" elif shape == 't': base = float(input("Enter base of the triangle: ")) height = float(input("Enter height of the triangle: ")) area = Triangle(base, height) s = "Triangle" elif shape == 'y': radius = float(input("Enter radius of cylinder: ")) height = float(input("Enter height of cylinder: ")) area = Cylinder(radius, height) s = "Cylinder" print("Area of %s is %f" %(s, area))

Figure 3.22: Program listing. An example run of the program is shown in Figure 3.23.

Figure 3.23: Example run of the program.

● 52

Chapter 4 • Amateur Radio Programs — Software Only

Chapter 4 • Amateur Radio Programs — Software Only 4.1 Overview Simple electronic engineering based example programs are given in this Chapter to make the reader familiar with programming the Raspberry Pi Pico using the Python language. The aim here has been to develop programs useful for the amateur radio operators. The programs given in this Chapter are software only and do not use any external hardware.

4.2 Examples 4.2.1 4-band resistor color code identifier In this project the user enters the three colors of a 4-band resistor, and the program calculates and displays the value of the resistor in ohms. The tolerance of the resistor is not displayed. The aim of this case study is to show how the keyboard input, lists and control statements can be used in a program. Resistor values are identified by the following color codes: Black: Brown: Red: Orange: Yellow: Green: Blue: Violet: Grey: White:

0 1 2 3 4 5 6 7 8 9

The first two colors determine the first two digits of the value while the last color determines the multiplier. For example, red - red - orange corresponds to 2 – 2 – 3 i.e., 22 × 103 = 22,000 ohms (Figure 4.1).

Figure 4.1: A 22,000 ohm resistor. Figure 4.2 shows the program listing (program: resistor.py). At the beginning of the program a list called colour is created which stores the valid resistor colors. Then a heading is displayed, and a while loop is created which runs as long as string variable yn is equal to y. Inside the loop the program reads the three colors from the keyboard using functions input and stores as strings in variables FirstColour, SecondColour and ThirdColour. These strings are then converted into lower case so that they are compatible with the values listed in the list box. The index values of these colors in the list are then found using function calls of the form colours.index. Remember that the index values start from 0. As an example,

● 53

Raspberry Pi Pico for Radio Amateurs

if the user entered red then the corresponding index value will be 2. The resistor value is then calculated by multiplying the first color number by 10 and adding to the second color number. The result is then multiplied by the power of 10 of the third color band. The final result is displayed on the screen. The program then asks whether or not the user wants to continue. If the answer is y, then the program returns to the beginning, otherwise the program is terminated. #================================================= #

RESISTOR COLOUR CODES

#

---------------------

# # The user enters the three colours of a resistor # and the program calculates and displays the value # of the resistor in Ohms # # Program: resistor.py # Date

: August, 2021

# Author : Dogan Ibrahim #=================================================== colours = ['black','brown','red','orange','yellow','green',\ 'blue','violet','grey','white'] print("RESISTOR VALUE CALCULATOR") print("=========================") yn = "y" while yn == 'y': FirstColour = input("Enter First Colour: ") SecondColour = input("Enter Second Colour: ") ThirdColour = input("Enter Third Colour: ") # # Convert to lower case # FirstColour = FirstColour.lower() SecondColour = SecondColour.lower() ThirdColour = ThirdColour.lower() # # Find the values of colours # FirstValue = colours.index(FirstColour) SecondValue = colours.index(SecondColour) ThirdValue = colours.index(ThirdColour) # # Now calculate the value of the resistor # Resistor = 10 * FirstValue

● 54

+ SecondValue

Chapter 4 • Amateur Radio Programs — Software Only

Resistor = Resistor * (10 ** ThirdValue) print("Resistance = %d Ohms" % (Resistor)) # # Ask for more # yn = input("\nDo you want to continue?: ") yn = yn.lower()

Figure 4.2: Program listing. Figure 4.3 shows a typical run of the program.

Figure 4.3: Typical run of the program.

4.2.2 4-band resistor color code identifier including small resistors The program given in Figure 4.2 can calculate the values of resistors if they are greater than or equal to 10 ohms. For smaller resistors, gold and silver colors are used as the third color. Gold divides the result by 10 and silver divides by 100. For example, red - red - silver corresponds to 0.22 ohms (Figure 4.4). This program calculates the values of all types of resistors identified by 4 color bands.

Figure 4.4: A 0.22 ohm resistor. Figure 4.5 shows the program listing (program: resistor2.py). Colors gold and silver are added to the list. The indexes of gold and silver in the list are 10 and 11, respectively. Most of the program is same as in Figure 4.2, except that if the third color is gold, then the result is divided by 10. Similarly, if the third color is silver then the result is divided by 100. Notice that if the resistor value is less than 10 ohms then it is displayed in floating-point format with two digits after the decimal point by using the print formatting parameter %3.2f.

● 55

Raspberry Pi Pico for Radio Amateurs

#================================================= #

RESISTOR COLOUR CODES

#

---------------------

# # The user enters the three colours of a resistor # and the program calculates and displays the value # of the resistor in Ohms. The program identifies all # types of resistors with 4 colour bands # # Program: resistor2.py # Date

: August, 2021

# Author : Dogan Ibrahim #=================================================== colours = ['black','brown','red','orange','yellow','green',\ 'blue','violet','grey','white', 'gold', 'silver'] print("RESISTOR VALUE CALCULATOR") print("=========================") yn = "y" while yn == 'y': FirstColour = input("Enter First Colour: ") SecondColour = input("Enter Second Colour: ") ThirdColour = input("Enter Third Colour: ") # # Convert to lower case # FirstColour = FirstColour.lower() SecondColour = SecondColour.lower() ThirdColour = ThirdColour.lower() # # Find the values of colours # FirstValue = colours.index(FirstColour) SecondValue = colours.index(SecondColour) ThirdValue = colours.index(ThirdColour) # # Now calculate the value of the resistor # Resistor = 10 * FirstValue

+ SecondValue

if ThirdValue == 10: Resistor = Resistor / 10.0 print("Resistance = %3.2f Ohms" % (Resistor)) elif ThirdValue == 11: Resistor = Resistor/100.0 print("Resistance = %3.2f Ohms" % (Resistor))

● 56

Chapter 4 • Amateur Radio Programs — Software Only

else: Resistor = Resistor * (10 ** ThirdValue) print("Resistance = %d Ohms" % (Resistor)) # # Ask for more # yn = input("\nDo you want to continue?: ") yn = yn.lower()

Figure 4.5: Program listing. Figure 4.6 shows a typical run of the program.

Figure 4.6: Typical run of the program.

4.2.3 Resistive potential divider In this example program we calculate the resistances in a resistive potential divider circuit. The aim of this case study is to show how to use the keyboard input and flow control statements in a program. Resistive potential divider circuits consist of two resistors. These circuits are used to lower a voltage to desired value. Figure 4.7 shows a typical resistive potential divider circuit. Here, Vin and Vo are the input and output voltages, respectively. R1 and R2 is the resistor pair used to lower the voltage from Vin to Vo. A large number of resistor pair can be used to get the desired output voltage. Choosing large resistors draw little current from the circuit, and choosing small resistors draw larger current. In this design the user specifies Vin, Vo, and R2. The program calculates the required R1 value to lower the voltage to the desired level. Additionally, the program displays the output voltage with the chosen physical resistors.

Figure 4.7: Resistive potential divider circuit.

● 57

Raspberry Pi Pico for Radio Amateurs

The output voltage is given by: Vo = Vin R2 / (R1 + R2)



R1 is then given by: R1 = (Vin – Vo) R2 / Vo



The above formula is used to calculate the required value of R1, given Vin, Vo, and R2. Figure 4.8 shows the program listing (program: divider.py). At the beginning of the program a heading is displayed. The program then reads Vin, Vo, and R2 from the keyboard. The program calculates R1 and displays R1 and R2. The user is then asked to enter a chosen physical value for R1. With the chosen value of R1, the program displays Vin, Vo, R1, and R2, and asks the user whether or not the result is acceptable. If the answer to this question is y, then the program terminates. If on the other hand the answer is n then the user is given the option of attempting again. #====================================================== #

RESISTIVE POTENTIAL DIVIDER

#

---------------------------

# # This is a resistive potential divider circuit program. # The program calculates the resistance values that will # lower the input voltage to the desired value # # Program: divider.py # Date

: August, 2021

# Author : Dogan Ibrahim #======================================================= print("RESISTIVE POTENTIAL DIVIDER") print("===========================") R1flag = 1 R2flag = 0 while R1flag == 1: Vin = float(input("\nInput voltage (Volts): ")) Vo = float(input("Desired output voltage (Volts): ")) R2 = float(input("Enter R2 (in Ohms): ")) # # Calculate R1 # R1 = R2 * (Vin - Vo) / Vo print("\nR1 = %3.2f Ohms R2 = %3.2f Ohms" %(R1, R2)) # # Read chosen physical R1 and display actual Vo

● 58

Chapter 4 • Amateur Radio Programs — Software Only

# NewR1 = float(input("\nEnter chosen R1 (Ohms): ")) # # Display and print the output voltage with chosen R1 # print("\nWith the chosen R1,the results are:") Vo = R2 * Vin / (NewR1 + R2) print("R1 = %3.2F R2 = %3.2f Vin = %3.2f Vo = %3.3f" %(NewR1,R2,Vin,Vo)) # # Check if happy with the values ? # happy = input("\nAre you happy with the values? ") happy = happy.lower() if happy == 'y': break else: mode = input("Do you want to try again? ") mode = mode.lower() if mode == 'y': R1flag = 1 else: R1flag = 0 break

Figure 4.8: Program listing. Figure 4.9 shows a typical run of the program.

Figure 4.9: Typical run of the program.

4.2.4 Resistive attenuator design — equal source & load resistances In this example we calculate the resistances in a resistive attenuator circuit where the source and the load resistances are equal. The aim of this case study is to show how to use the keyboard input, flow control statements, and logarithms in a program.

● 59

Raspberry Pi Pico for Radio Amateurs

A resistive attenuator is a two-port resistive circuit designed to attenuate the power applied to its input terminals. Attenuators are generally used in radio, audio, and communication circuits to reduce a stronger signal, as well as to provide impedance matching between a source and a load. The performance of an attenuator is expressed by the number of decibels (dB) the input signal has decreased. Expressed mathematically, the logarithm to base 10 of the ratio of the output signal to the input signal, multiplied by 20 is known as the decibel:

dB = 20 log10 Vo / Vin (4.1)

For example, if the ratio of output/input voltage is 0.707, this corresponds to –3 dB. Similarly, a ratio of 0.5 corresponds to –6 dB. To find the actual voltage ratio with a given dB, we have to take the anti-logarithm as given by the following formula:

Vo / Vin = antilog10 (dB / 20) (4.2)

As an example, –10dB corresponds to the voltage ratio of Vo / Vin = antilog10 (–0.5) = 0.316 There are many types of resistive attenuator circuits in use, but the commonly used ones are the T and Pi type circuits, having 3 resistors each. Figure 4.10 shows the T-type attenuator with two identical resistors R1 and a single resistor R2.

Figure 4.10: Resistive T-type attenuator. The design equations of this circuit are as follows (see the website: https://www.electronics-tutorials.ws/attenuators/pi-pad-attenuator.html for more details). The source and the load resistances are assumed to be equal in this design:

(4.3)

(4.4)

● 60

Chapter 4 • Amateur Radio Programs — Software Only

Where, Z is the source resistance, which is also equal to the load resistance, and K is known as the attenuation factor, where:

K = antilog10(dB / 20) = 10dB/20

For example, for a 6 dB attenuation, K will be 106/20 = 1.9953. Alternatively, if we want to attenuate the input signal by a factor of 12, then the value of K will be 12. Figure 4.11 shows the Pi-type resistive attenuator again with two identical resistors R1 and a single resistor R2.

Figure 4.11: Resistive Pi-type attenuator. The design equations of this circuit are as follows (see web site: https://www.electronics-tutorials.ws/attenuators/pi-pad-attenuator.html for more details). The source and the load resistances are assumed to be equal in this design:

(4.5)

(4.6) Where, Z is the source resistance, which is also equal to the load resistance, and K is the impedance factor as before. Figure 4.12 shows the program listing (program: attenuator.py). After displaying a heading, the user is prompted to enter the source (which is also the load) resistance Z, attenuation factor K in decibels, and the type of circuit to be used as T or P (for "Pi"). The program calculates and displays the values of the resistors.

● 61

Raspberry Pi Pico for Radio Amateurs

#---------------------------------------------------#



RESISTIVE ATTENUATOR DESIGN

#



===========================

# # This program designs a T or Pi type resistive # attenuator. The user enters the source (also load) # resistance, atenuation factor and type of design # # Author: Dogan Ibrahim # File

: attenuator.py

# Date

: August, 2021

#---------------------------------------------------print("Resistive Attenuator Design") print("===========================") Z = float(input("Enter source resistance in Ohms: ")) Kdb = float(input("Enter attenuation Factor in dB: ")) T = input("Enter attenuator type (T or P): ") T = T.lower() K = pow(10.0, Kdb/20.0) if T == 't': R1 = Z * (K - 1) / (K + 1) R2 = R1 R3 = 2 * Z * K / (K * K - 1) elif T == 'p': R1 = Z * (K + 1) / (K - 1) R3 = R1 R2 = Z * (K * K - 1) / (2 * K) print("\nResults:") print("-------") print("Z = %f Ohms\nK = %f dB\nK (Vi/Vo) = %f\nR1=%f Ohms\nR2=%f Ohms\ \nR3=%f Ohms" %(Z, Kdb, K, R1, R2, R3))

Figure 4.12: Program listing. An example run of the program is shown in Figure 4.13. The design parameters are as follows: Source (load) resistance, Z = 50 ohms Attenuation factor = 12 decibels Attenuation type = T The designed circuit is shown in Figure 4.14.

● 62

Chapter 4 • Amateur Radio Programs — Software Only

Figure 4.13: Example run of the program.

Figure 4.14: Designed attenuator circuit.

4.2.5 Resistive attenuator design — unequal source & load resistances In this example we calculate the resistances in a resistive attenuator circuit where the source and the load resistances may not be equal. The aim of this case study is to show how to use the keyboard input, flow control statements, and logarithms within a program. In an attenuator where the source and the load resistances are not equal, different formula are used to calculate the resistance values. In this section we will only consider a Pi-type network shown in Figure 4.15.

Figure 4.15: Pi-type attenuator with different source and load resistances. The design equations are as shown in Figure 4.16.

● 63

Raspberry Pi Pico for Radio Amateurs

Figure 4.16: Pi attenuator design equations. Figure 4.17 shows the program listing (program: attenuator2.py). After displaying a heading, the user is prompted to enter the source and the load resistances ZS and ZL, and the attenuation factor K in decibels. The program calculates and displays the values of the resistors. #---------------------------------------------------#



RESISTIVE Pi ATTENUATOR DESIGN

#



==============================

# # This program designs a Pi type resistive attenuator # where the source and the load resistances may be # different to each other # # Author: Dogan Ibrahim # File

: attenuator2.py

# Date

: August, 2021

#---------------------------------------------------import math print("Resistive Attenuator Design With Different Source & Load") print("========================================================") ZS = float(input("Enter source resistance in Ohms: ")) ZL = float(input("Enter load resistance in Ohms: ")) Kdb = float(input("Enter attenuation Factor in dB: ")) K = pow(10.0, Kdb/20.0) R1 = ZS * ((K * K - 1) / (K * K - 2 * K * math.sqrt(ZS / ZL) + 1))

● 64

Chapter 4 • Amateur Radio Programs — Software Only

R2 = 0.5 * (math.sqrt(ZS * ZL)) * (K * K - 1) / K R3 = ZL * ((K * K - 1) / ( 1 + K * K - (2 * K / math.sqrt(ZS/ZL)))) print("\nResults:") print("-------") print("ZS = %f Ohms\nZL = %f Ohms\nK = %f dB\nK (Vi/Vo) = %f\nR1=%f Ohms\nR2=%f Ohms\nR3=%f Ohms"%(ZS, ZL, Kdb, K, R1, R2, R3))

Figure 4.17: Program listing. An example run of the program is shown in Figure 4.18. The design parameters are as follows: Source resistance, ZS = 75 ohms Load resistance, ZL = 50 ohms Attenuation factor = 6 decibels

Figure 4.18: Example run of the program. The designed circuit is shown in Figure 4.19.

Figure 4.19: Designed attenuator circuit.

4.2.6 Zener diode based voltage regulator There are many occasions where amateur radio operators need low-cost simple constant voltage regulators. In this example we will give a program to help design a zener diode based voltage regulator circuit.

● 65

Raspberry Pi Pico for Radio Amateurs

Zener diodes (Figure 4.20) are used in voltage regulator circuits. A zener diode is like a general-purpose diode. When the diode is biased in the forward direction it behaves just like a normal signal diode, but when biased in the reverse direction, the voltage remains constant for a wide range of currents. As a result of this characteristic, zener diodes are used as fixed-voltage sources in power supply applications.

Figure 4.20: Zener diode. The typical forward voltage of the diode at 1 mA current is around 0.6 volts. As shown in Figure 4.21, in the reverse direction a small leakage current flows. As the breakdown voltage is approached, the current begins to avalanche and the voltage across the zener diode becomes nearly constant. There is a minimum current that puts the device into the breakdown region, and a maximum current at which point the device can be damaged if the current is increased.

Figure 4.21: Typical zener diode characteristics. Zener diodes are available in values from about 2.4 V to 200 V and some popular ones are rated at 2.7 V, 3.3 V, 4.7 V, 5.1 V, 10 V, 12 V, 15 V, etc.

● 66

Chapter 4 • Amateur Radio Programs — Software Only

Figure 4.22 shows a zener diode used as a voltage regulator. The input voltage is applied to the cathode terminal of the diode through a resistor and the output voltage is taken across the diode. The design of a zener diode regulator circuit depends on the correct choice of the resistor.

Figure 4.22: Zener diode based voltage regulator. The calculation of resistor Rs depends on the load current requirements and its minimum value is given by: Rs = (Vin – Vz) / (Izmin + ILmax) (4.7)



Where Vin is the input voltage, Vz is the zener voltage, Izmin is the minimum zener current (or zener test current in data sheets), and ILmax is the maximum load current. Before choosing a zener diode for an application, we have to make sure that the maximum power rating of the diode is not exceeded when there is no load. This is given by: Pz = Vz × Is (4.8)



Where Is = (Vin – Vz) / Rs (4.9) The power rating of the resistor is calculated as: PRs = (Vin – Vz) × Is (4.10)



Figure 4.23 shows the program listing (program: zener.py). At the beginning of the program a heading is displayed, and the user is prompted to enter Vin, Vz, Izmin, and ILmax. The required resistor value, the minimum power ratings of the resistor, and the zener diode are calculated and displayed. #---------------------------------------------------#

ZENER DIODE VOLTAGE REGULATOR

#

=============================

# # This is a zener diode based voltage regulator design # program which calculates the required resistance value # # Author: Dogan Ibrahim # File

: zener.py

# Date

: August, 2021

● 67

Raspberry Pi Pico for Radio Amateurs

#---------------------------------------------------print("Zener Diode Voltage Regulator") print("=============================") Vin = float(input("Enter Vin (Volts): ")) Vz = float(input("Enter zener (load) voltage (Volts): ")) Izmin = float(input("Enter minimum zener current (mA): ")) IzminA = Izmin / 1000.0 ILmax = float(input("Enter maximum load current (mA): ")) ILmaxA = ILmax / 1000.0 # # Now do the calculations # Rs = (Vin - Vz) / (IzminA + ILmaxA) Is = (Vin - Vz) / Rs Pz = Vz * Is Pz = Pz * 1000.0 Prs = (Vin - Vz) * Is Prs = Prs * 1000.0 # # Display the results # print("\nResults") print("=======") print("Vin=%3.2fV\nVz=%3.2fV\nIzmin=%3.2fmA\nILmax=%3.2fmA\nRs=%3.2f Ohms\ \nPrs=%3.2fmW\nPz=%3.2fmW" %(Vin, Vz, Izmin, ILmax, Rs, Prs, Pz))

Figure 4.23: Program listing. An example run of the program is shown in Figure 4.24, which has the following specifications: Vin = 10 V Vz = 5.1 V Izmin = 5 mA ILmax = 100 mA

● 68

Chapter 4 • Amateur Radio Programs — Software Only

Figure 4.24: Example run of the program. Figure 4.25 shows the designed zener diode circuit where the output voltage is 5.1 V. The required resistor value is calculated to be 46.67 ohms. We should choose 47 ohms, 1 watt, as the nearest physical resistor. The 5.1 V zener diode should have a 1-watt power rating approximately.

Figure 4.25: Designed zener diode circuit.

4.2.7 RC circuit frequency response RC circuits are commonly used in amateur radio as simple passive filters. In this example we will calculate the frequency response (magnitude and phase) of an RC circuit and tabulate the results on the screen. The frequency response of a circuit consists of the change of its magnitude and the phase angle as the frequency is changed. In this case study we will consider a simple RC circuit shown in Figure 4.26 with the component values, R = 470 ohms and C = 20 microfarads, where the capacitor is the output. The magnitude (transfer function) and phase of the frequency response of this circuit are given by the following formula:

(4.11) The magnitude is usually denoted in decibels:

(4.12)

● 69

Raspberry Pi Pico for Radio Amateurs

And the phase is: (4.13) Where, W = 2πf, and f is the frequency. In this case study we will calculate the magnitude in decibels and the phase in degrees as the frequency is changed from 0 to 150 Hz in steps of 10 Hz.

Figure 4.26: RC Circuit used in the case study. Figure 4.27 shows the program listing (program: freqrc.py). At the beginning of the program the values of R and C are read from the keyboard. The program then calculates the magnitude in decibels and the phase angle in degrees as the frequency is changed and saves the results in the file. #=================================================== #

Frequency Response of RC circuit

# ================================ # # This program calculates the frequency reponse of # an RC circuit and tabulates the results # # Author: Dogan Ibrahim # File:

freqrc.py

# Date:

August, 2021

#=================================================== import math print("RC Frequency Response") print("=====================") # # Read in the component values # R = float(input("Enter R in Ohms: ")) C = float(input("Enter C in microfarads: ")) C = C / 1000000.0 print("Frequency (Hz)

● 70

Magnitude (dB)

Phase (degrees)\n")

Chapter 4 • Amateur Radio Programs — Software Only

for freq in range(0, 160, 10): w = 2.0 * freq * math.pi d = w * C * R denom = d * d + 1 M = math.sqrt(1 / denom) M = 20 * math.log10(M) phase = -math.degrees(math.atan(d)) print("%3d

%10.4f

%10.4f" %(freq, M, phase))

Figure 4.27: Program listing. Figure 4.28 shows the frequency response on the screen.

Figure 4.28: Output of the program.

4.2.8 Resonance in series RLC circuits In this example, we read the resistance, inductance and capacitance in a series-connected RLC circuit and then calculate and display the resonance frequency, current in the circuit at resonance, voltage across the inductor and capacitor at resonance, the Q factor, the bandwidth of the circuit, and the upper and lower –3 dB points at resonance. In a series-resonance RLC circuit there is a frequency point where the capacitive reactance of the capacitor becomes equal to the inductive reactance of the inductor. The point at which this occurs is called the resonant frequency of the circuit. Series-resonance circuits are used as tuned circuits in communication systems, mains filters, noise filters, etc. The resonant frequency fr of an RLC circuit is given by the following formula:

(4.14)

● 71

Raspberry Pi Pico for Radio Amateurs

The circuit current at resonance is given by: (4.15) The inductive reactance at resonance is given by: (4.16) The voltage across the inductor and capacitor at resonance are given by: (4.17) The Q factor of a resonant circuit is given by:

(4.18) The bandwidth is given by:

(4.19) The upper and lower –3dB frequency points are given by:

(4.20) And

(4.21) Figure 4.29 shows the definition of Bandwidth in a resonant circuit.

● 72

Chapter 4 • Amateur Radio Programs — Software Only

Figure 4.29: Bandwidth in a resonant circuit. Figure 4.30 shows the program listing (program: resonance.py). The program reads the values of the resistance, inductance, capacitance, and the applied voltage, and calculates the various circuit values at resonance. The calculated values are displayed on the screen. #============================================================== #

Series RLC Circuit Resonance Calculations

# ========================================= # # This program reads the values RLC and calculates and # displays all the resonace related values # # Author: Dogan Ibrahim # File

: resonance.py

# Date

: August 2021

#============================================================== import math # # Read the circuit components # R = float(input("Enter R: ")) L = float(input("Enter L: ")) C = float(input("Enter C: ")) V = float(input("Enter V: ")) L = L /1000.0

# convert to Henries

C = C / 1000000.0

# convert to Farads

# # Now carry out the calculations #

● 73

Raspberry Pi Pico for Radio Amateurs

LC = math.sqrt(L * C) fr = 1.0 / (2*math.pi*LC)

# resonant frequency

Ir = V / R

# current in circuit

Xl = 2 * math.pi * fr * L

# inductive reactance

Vl = Ir * Xl

# Voltage across L and C

Q = 2 * math.pi * fr * L / R

# Q factor

BW = fr / Q

# Bandwidth

fl = fr - BW / 2

# lower -3dB freq

fh = fr + BW / 2

# higher -3dB freq

print("fr(Hz)

= %10.2f" %(fr))

print("I(A)

= %10.2f" %(Ir))

print("X1 (Ohms)

= %10.2f" %(Xl))

print("V1 (Volts) = %10.2f" %(Vl)) print("Q

= %10.2f" %(Q))

print("BW

= %10.2f" %(BW))

print("fl (Hz)

= %10.2f" %(fl))

print("fh (Hz)

= %10.2f" %(fh))

Figure 4.30: Program listing. Figure 4.31 shows a typical run of the program. Notice that the resistance is entered in ohms, capacitance in microfarads, inductance in millihenries, and voltage in volts. The frequency is displayed in hertz.

Figure 4.31: Typical run of the program.

4.2.9 Calculating the inductance of a single-layer coil Single-layer coils are used in nearly every piece of communications equipment. In this example, we will calculate the inductance of an air-core, single-layer coil, given its diameter, length, and the number of turns. The inductance of a single-layer air core coil can be calculated using Wheeler's formula. The formula, given below, is accurate to within 1% for L / D > 0.4 i.e., the coil is not too short. For short coils, this formula is not very suitable:

● 74

Chapter 4 • Amateur Radio Programs — Software Only

(4.22) Where L is the inductance in microhenries, N is the number of turns, D is the diameter of the coil in cm, and Len is the length of the coil in cm. Figure 4.32 shows the program listing (program: coil.py). The program reads D, N, and L from the keyboard. The inductance is then calculated and displayed. The user is warned that the results may not be accurate if the coil is not short. Figure 4.33 shows a typical run of the program. #===================================================================== #

Inductance of a Single Layer Coil

#

=================================

# # This program calculates the inductance of a single layer air # core coil. Number of turns,diameter,and length are read from keyboard # # Author: Dogan Ibrahim # File

: coil.py

# Date

: August 2021

#===================================================================== N = float(input("Enter Number of turns: ")) D = float(input("Enter Diameter (cm): ")) L = float(input("Enter Length (cm): "))

# # Now carry out the calculation and display the inductance # Ind = (D * D * N * N) / (45 * D + 100* L) print("Inductance = %10.4f" %(Ind)) if L / D = 7: if sdata[6] == "V":

# Valid data?

lcd.clear()

# Clear LCD

lcd.move_to(0, 0)

# At 0,0

lcd.putstr("NO DATA")

# No data



return lat = sdata[1]

# Get latitude

latdir = sdata[2]

# Latitude dir

lon = sdata[3]

# Get longitude

londir = sdata[4]

# Longitude dir

flag=1 return else: lcd.clear() lcd.putstr("wait...") utime.sleep(1) while flag == 0: data = uart.readline() Get_GPS(data)

# Decode

flag=1 deg = lat[0:2] min = lat[2:] latitude = str(deg) + " " + str(min) + "

" + str(latdir)

deg = lon[0:3] min = lon[3:] longitude = str(deg) + " " + str(min) + " " + str(londir)

● 142

Chapter 6 • Amateur Radio Hardware-based Projects

lcd.clear() lcd.move_to(0, 0) lcd.putstr(latitude)



# Display latitude

lcd.move_to(0, 1) lcd.putstr(longitude)



# Display longitude

Figure 6.22: Program: gps.py. An example display on the LCD is shown in Figure 6.23

Figure 6.23: Example display on the LCD. Using a second I2C LCD In this and in the earlier projects using I2C LCD, the I2C device address is set to 0x27 by default. It is possible to use more than one LCD in a project as long as they have different I2C addresses. The address of the LCD can be set by soldering jumpers across the 6 pads marked as A0, A1, and A2 at the back of the LCD as shown in Figure 6.24:

Figure 6.24: I2C LCD address jumpers.

● 143

Raspberry Pi Pico for Radio Amateurs

The address selection is as follows, where 1 corresponds to a jumper solder across the two specified pads: A2 A1 A0 Address No jumpers 0x27 (default) 0 0 1 0x26 0 1 0 0x25 0 1 1 0x24 1 0 0 0x23 1 0 1 0x22 1 1 0 0x21 1 1 1 0x20

6.6 Waveform generation – using software Waveform generators are important tools for amateur radio operators. There is many commercially available equipment for generating various waveforms. In this section, we will be developing projects to generate various analog waveforms such as square, sine, triangular, staircase, etc., by programming the Raspberry Pi Pico. Before generating an analog waveform, it is necessary to use a Digital-to-Analog Converter chip (DAC) to convert the generated digital signals into analog form. The Raspberry Pi Pico has no built-in DAC converter, calling for an external DAC chip to be used to output analog signals. In this book, we will be using the popular MCP4921 DAC chip from Microchip. DACs are used to convert digital signals into analog form. Such converters have many applications in digital signal processing and digital control applications. For example, we can generate waveforms by writing programs and then convert these waveforms into analog forms and output them from our digital computer. We also need DACs if we want to interface a speaker or some other device operating with analog voltages to our Raspberry Pi Pico. The MCP4921 DAC Before using the MCP4921, it is worthwhile to look at its features and operation in some detail. The MCP4921 is a 12-bit DAC that operates with the SPI bus interface. Figure 6.25 shows the pin layout of this chip. The basic features are (12-bit operation): • 20MHz clock support • 4.5μs settling time • External voltage reference input • Unity or 2x Gain control • 1x or 2x gain • 2.7 to 5.5V supply voltage • -40ºC to +125ºC temperature range

● 144

Chapter 6 • Amateur Radio Hardware-based Projects

for more details, review:



http://ww1.microchip.com/downloads/en/devicedoc/21897b.pdf.

Figure 6.25: The Microchip MCP4921 DAC] The pin descriptions are: Vdd: CS: SCK: SDI: LDAC: Vref Vout: Vss:

supply voltage chip select (active LOW) SPI clock SPI data in Used to transfer input register data to the output (active LOW) Reference input voltage analog output supply ground

In this project we will be operating the MCP4921 with a gain of 1. As a result, with a reference voltage of 3.3 V and 12-bit conversion data, the LSB resolution of the DAC will be 3300 mV / 4096 = 0.8 mV

6.6.1 Project 5: Generating a squarewave signal with amplitude under +3.3 V In this project we will be using the DAC to generate a squarewave signal with a frequency of 500 Hz (Period = 2 ms), and 50% duty cycle (i.e., ON time = 1 ms, OFF time = 1 ms). The output voltage will be 2 Vpeak (notice that this could not have been achieved without using a DAC since the output HIGH voltage of a pin is +3.3 V). Figure 6.26 shows the block diagram of the project.

Figure 6.26: Block diagram of the project.

● 145

Raspberry Pi Pico for Radio Amateurs

The circuit diagram of the project is shown in Figure 6.27. Pin GP3 (SPI0 TX) and GP2 (SPIO SCK) are connected to MCP4921 pins SDI and SCK, respectively. The CS of MCP4921 is controlled separately from GP16 (pin 21). The output of the DAC is connected to the oscilloscope.

Figure 6.27: Circuit diagram of the project. Data is written to the DAC in two bytes. The lower byte specifies D0:D8 of the digital input data. The upper byte consists of the following bits: D8:D11 bits D8:D11 of the digital input data SHDN 1: active (output available), 0: shut down the device GA output gain control. 0: gain is 2×, 1: gain is 1× BUF 0: input unbuffered, 1: input buffered A/B 0: write to DACa, 1: Write to DACb (the MCP4921 supports DACa only) In normal operation, you send the upper byte (D8:D11) of the 12 bit (D0:D11) input data with bits D12 and D13 set to 1 so that the device is active, and the gain is set to 1x. Then you send the low byte (D0:D7) of the data. This means that 0x30 should be added to the upper byte before sending it to the DAC. Figure 6.28 shows the program listing (program: Square). Since we are using a DAC with the reference voltage set to +3.3 V (3300 mV), and 12-bit wide data (i.e., 4096 steps), the required digital value to set the output voltage to 2 V is given by ONvalue, where:

ONvalue = 2000 × 4095 / 3300

The OFF value of the signal (OFFvalue) is set to 0V. Function DAC configures the DAC so that 2 V is output from it. First the HIGH byte (in buff[0]) is put into a buffer, followed by the LOW byte (in buff[1]):

● 146

Chapter 6 • Amateur Radio Hardware-based Projects

buff[0] = (data >> 8) & 0x0F buff[0] = buff[0] + 0x30 buff[1] = data & 0xFF spi.write(bytearray(buff)) The duration of the ON and OFF times is set to 1 ms. However, it was found from the experiments that the DAC routine takes some time and because of this, the period and consequently the frequency of the output waveform are not perfectly accurate. The ON and OFF times are slightly bigger than 1 ms. Readers can experiment to adjust the delay to get exactly 1 ms if required. #---------------------------------------------------------#

GENERATE SQUARE WAVE SIGNAL WITH AMPLITUDE +2V

#

==============================================

# # In this project a MCP4921 type DAC chip is connected to the # Raspberry Pi Pico.The program generates a square wave signal # with frequency f=500Hz, 50% duty cycle (ON and OFF tiems equal # and each 1ms), and 2V amplitude # # Author: Dogan Ibrahim # File

: Square.py

# Date

: August 2021

#-----------------------------------------------------------from machine import Pin, SPI import utime spi_sck = Pin(2)

# SCK pin at GP2

spi_tx = Pin(3)

# TX pin at GP3

spi_rx = Pin(0)

# RX pin at GP0 (not used)

spi = SPI(0,sck=spi_sck,mosi=spi_tx,miso=spi_rx,baudrate=100000) CS = Pin(16, Pin.OUT)

# CS

CS.value(1) # Disable chip ONvalue = int(2000 * 4095 / 3300)

# For +2V amplitude

OFFvalue = 0 def DAC(data): buff = [0, 0] buff[0] = (data >> 8) & 0x0F

# HIGH byte

buff[0] = buff[0] + 0x30 buff[1] = data & 0xFF

# LOW byte

CS.value(0)

# Enable MCP4921

spi.write(bytearray(buff)) # Send to SPI bus

● 147

Raspberry Pi Pico for Radio Amateurs

CS.value(1)

# DIsable MCP4921

# # Main program # while True: DAC(ONvalue) utime.sleep_ms(1000) DAC(OFFvalue) utime.sleep_ms(1000)

Figure 6.28: Program: Square. Figure 6.29 shows the output waveform generated by the program. This waveform was captured using a type PCSGU250 digital oscilloscope. The horizontal axis was set to 1 ms/ division and the vertical axis was 1 V / division. The peak output voltage is 2 V as expected.

Figure 6.29: Output waveform. Using timer interrupt for accurate timing As we have seen in Figure 6.29, the period of the waveform is not exactly 2 ms. In this section we will be using timer interrupts to achieve more accurate timing. Figure 6.30 shows te new program listing (Program: Square2). In this version of the program a variable called flag is used to output the ON and the OFF times alternately. The timer works in the background and calls function DAC 1000 times a second (i.e., 500 ON pulses and 500 OFF pulses).

● 148

Chapter 6 • Amateur Radio Hardware-based Projects

#---------------------------------------------------------#

GENERATE SQUARE WAVE SIGNAL WITH AMPLITUDE +2V

#

==============================================

# # In this project a MCP4921 type DAC chip is connected to the # Raspberry Pi Pico.The program generates a square wave signal # with frequency f=500Hz, 50% duty cycle (ON and OFF tiems equal # and each 1ms), and 2V amplitude # # This version of the program uses timer interrupts # # Author: Dogan Ibrahim # File

: Square2.py

# Date

: August 2021

#-----------------------------------------------------------from machine import Pin, SPI, Timer #import utime spi_sck = Pin(2)

# SCK pin at GP2

spi_tx = Pin(3)

# TX pin at GP3

spi_rx = Pin(0)

# RX pin at GP0 (not used)

spi = SPI(0,sck=spi_sck,mosi=spi_tx,miso=spi_rx,baudrate=100000) CS = Pin(16, Pin.OUT)

# CS

CS.value(1) # Disable chip ONvalue = int(2000 * 4095 / 3300)

# For +2V amplitude

OFFvalue = 0 tim = Timer() flag = 0 # # Timer interrupt service routine # def DAC(timer): global flag, Onvalue, OFFvalue global CS buff = [0, 0] if flag == 0: data = ONvalue flag = 1 else: data = OFFvalue flag = 0

● 149

Raspberry Pi Pico for Radio Amateurs

buff[0] = (data >> 8) & 0x0F

# HIGH byte

buff[0] = buff[0] + 0x30 buff[1] = data & 0xFF

# LOW byte

CS.value(0)

# Enable MCP4921

spi.write(bytearray(buff))

# Send to SPI bus

CS.value(1)

# DIsable MCP4921

# # Main program # tim.init(freq = 1000, mode = Timer.PERIODIC, callback = DAC)

Figure 6.30 Program: Square2. Figure 6.31 shows the new output. It is clear that the period of the waveform is exactly 2 ms (i.e., frequency of exactly 500 Hz).

Figure 6.31: Output waveform.

6.6.2 Project 6: Generating fixed voltages In this project, we will be using the DAC to generate fixed voltages. Voltages with amplitudes 0, 1, 2, and 3 V with 100 ms delay between each voltage will be generated. The block diagram and circuit diagram may be found in Figure 6.26 and Figure 6.27, respectively. Figure 6.32 shows the program listing (Program: FixedV). Function 'Voltage' converts the voltage into digital value for 12-bits and returns it to the main program.

● 150

Chapter 6 • Amateur Radio Hardware-based Projects

#---------------------------------------------------------#

GENERATE FIXED VOLTAGES

#

=======================

# # In this project a MCP4921 type DAC chip is connected to the # Raspberry Pi Pico.The program generates fixed voltages with # amplitues 0, 1, and 2V and the delay between each output # being 100ms # # Author: Dogan Ibrahim # File

: FixedV.py

# Date

: February 2021

#-----------------------------------------------------------from machine import Pin, SPI import utime spi_sck = Pin(2)

# SCK pin at GP2

spi_tx = Pin(3)

# TX pin at GP3

spi_rx = Pin(0)

# RX pin at GP0 (not used)

spi = SPI(0,sck=spi_sck,mosi=spi_tx,miso=spi_rx,baudrate=100000) CS = Pin(16, Pin.OUT)

# CS

CS.value(1) # Disable chip def Voltage(V): Amplitude = int(V * 4095 / 3300) return Amplitude def DAC(data): buff = [0, 0] buff[0] = (data >> 8) & 0x0F

# HIGH byte

buff[0] = buff[0] + 0x30 buff[1] = data & 0xFF

# LOW byte

CS.value(0)

# Enable MCP4921

spi.write(bytearray(buff))

# Send to SPI bus

CS.value(1)

# DIsable MCP4921

# # Main program # while True: DAC(Voltage(0)) utime.sleep_ms(100) DAC(Voltage(1000)) utime.sleep_ms(100)

● 151

Raspberry Pi Pico for Radio Amateurs

DAC(Voltage(2000)) utime.sleep_ms(100) DAC(Voltage(3000)) utime.sleep_ms(100)

Figure 6.32: Program: FixedV. Figure 6.33 shows the generated output waveform.

Figure 6.33: Output waveform.

6.6.3 Project 7: Generating a sawtooth signal In this project we will be using the DAC to generate a sawtooth signal with the following specifications: Peak voltage: Step width: Number of steps:

3.3 V 2 ms 10

The block diagram and circuit diagram are again found in Figure 6.26 and Figure 6.27, respectively. Figure 6.34 shows the program listing (Program: Sawtooth). Function 'Voltage' converts the voltage into digital value for 12 bits and returns it to the main program. Notice that as described earlier, the timing of the generated signal is not perfectly accurate and timer interrupts can be used to generate accurate output.

● 152

Chapter 6 • Amateur Radio Hardware-based Projects

#---------------------------------------------------------#

GENERATE SAWTOOTH WAVEFORM

#

==========================

# # In this project a MCP4921 type DAC chip is connected to the # Raspberry Pi Pico.The program generates sawtooth waveform # having 10 steps # # Author: Dogan Ibrahim # File

: Sawtooth.py

# Date

: August 2021

#-----------------------------------------------------------from machine import Pin, SPI import utime spi_sck = Pin(2)

# SCK pin at GP2

spi_tx = Pin(3)

# TX pin at GP3

spi_rx = Pin(0)

# RX pin at GP0 (not used)

spi = SPI(0,sck=spi_sck,mosi=spi_tx,miso=spi_rx,baudrate=100000) CS = Pin(16, Pin.OUT)

# CS

CS.value(1) # Disable chip def Voltage(V): Amplitude = int(V * 4095 / 3300) return Amplitude def DAC(data): buff = [0, 0] buff[0] = (data >> 8) & 0x0F

# HIGH byte

buff[0] = buff[0] + 0x30 buff[1] = data & 0xFF

# LOW byte

CS.value(0)

# Enable MCP4921

spi.write(bytearray(buff))

# Send to SPI bus

CS.value(1)

# DIsable MCP4921

# # Main program # k = 0.0 while True: DAC(int(Voltage(k*3300))) utime.sleep_ms(2) k = k + 0.1 if k == 1.0:

● 153

Raspberry Pi Pico for Radio Amateurs

k = 0.0

Figure 6.34: Program: Sawtooth. Figure 6.35 shows the generated output waveform. Here, the horizontal axis was 10 ms / division, and the vertical axis was 1 V / division.

Figure 6.35: Output waveform.

6.6.4 Project 8: Generating a triangular-wave signal In this project we will be using the DAC to generate a triangular-wave signal having 10 steps going up and 10 steps going down. The step width is set to 1 ms. The block diagram and circuit diagram found in Figure 6.26 and Figure 6.27, respectively. Figure 6.36 shows the program listing (Program: Triangle). Function 'Voltage' converts the voltage into digital value for 12 bits and returns it to the main program. #----------------------------------------------------------

# GENERATE TRIANGLE WAVEFORM # ========================== # # In this project a MCP4921 type DAC chip is connected to the # Raspberry Pi Pico.The program generates triangle waveform # # Author: Dogan Ibrahim # File : Triangle.py # Date : August 2021 #-----------------------------------------------------------from machine import Pin, SPI import utime

● 154

Chapter 6 • Amateur Radio Hardware-based Projects

spi_sck = Pin(2) spi_tx = Pin(3) spi_rx = Pin(0)

# SCK pin at GP2 # TX pin at GP3 # RX pin at GP0 (not used)

spi = SPI(0,sck=spi_sck,mosi=spi_tx,miso=spi_rx,baudrate=100000) CS = Pin(16, Pin.OUT) # CS CS.value(1) # Disable chip def Voltage(V): Amplitude = int(V * 4095 / 3300) return Amplitude def DAC(data): buff = [0, 0] buff[0] = (data >> 8) & 0x0F buff[0] = buff[0] + 0x30 buff[1] = data & 0xFF CS.value(0) spi.write(bytearray(buff)) CS.value(1) # # Main program # while True: k = 0.0 while k < 1.0: DAC(int(Voltage(k*3300))) utime.sleep_ms(1) k = k + 0.1 k = 1.0 while k > 0.0: DAC(int(Voltage(k*3300))) utime.sleep_ms(1) k = k - 0.1

# HIGH byte # # # #

LOW byte Enable MCP4921 Send to SPI bus DIsable MCP4921

# Going up

# Going down

Figure 6.36: Program: Triangle. Figure 6.37 shows the generated output waveform. Notice again that, as described earlier, the timing of the generated signal is not perfectly accurate and timer interrupts can be used to generate accurate output.

● 155

Raspberry Pi Pico for Radio Amateurs

Figure 6.37: Output waveform.

6.6.5 Project 9: Arbitrary periodic waveform In this project we will generate an arbitrary periodic waveform with a period of 20 ms. The details of the waveform are as shown in Figure 6.38.

Figure 6.38: The waveform to be generated. The waveform takes the following values: Time (ms) Amplitude (V) 0 0 1 0.2 2 0.4 3 0.6 4 0.8 5 1.0 6 1.2

● 156

Time (ms) Amplitude (V) 11 1.6 12 1.6 13 1.4 14 1.2 15 1.0 16 0.8 17 0.6

Chapter 6 • Amateur Radio Hardware-based Projects

7 8 9 10

1.4 1.6 1.6 1.6

18 19 20

0.4 0.2 0.0

The block diagram and circuit diagram are found in Figure 6.26 and Figure 6.27, respectively. Figure 6.39 shows the program listing (Program: Arbitrary). The voltage samples are stored in the list named 'Waveform'. Inside the main program, a loop runs from 0 to 20 (inclusive), gets the required voltage amplitude at every sample, and calls the DAC to generate the required sample. #---------------------------------------------------------#

GENERATE ARBITRARY WAVEFORM

#

===========================

# # In this project a MCP4921 type DAC chip is connected to the # Raspberry Pi Pico.The program generates an arbitarry waveform # whose characteristics are defined in the text # # Author: Dogan Ibrahim # File

: Arbitrary.py

# Date

: August 2021

#-----------------------------------------------------------from machine import Pin, SPI import utime import math spi_sck = Pin(2)

# SCK pin at GP2

spi_tx = Pin(3)

# TX pin at GP3

spi_rx = Pin(0)

# RX pin at GP0 (not used)

spi = SPI(0,sck=spi_sck,mosi=spi_tx,miso=spi_rx,baudrate=100000) CS = Pin(16, Pin.OUT)

# CS

CS.value(1) # Disable chip Waveform = [0.0,0.2,0.4,0.6,0.8,1.0,1.2,1.4,1.6,1.6,1.6,1.6,1.6, 1.4,1.2,1.0,0.8,0.6,0.4,0.2,0.0] def Voltage(V): Amplitude = int(V * 4095 / 3.3) return Amplitude def DAC(data):

● 157

Raspberry Pi Pico for Radio Amateurs

buff = [0, 0] buff[0] = (data >> 8) & 0x0F

# HIGH byte

buff[0] = buff[0] + 0x30 buff[1] = data & 0xFF

# LOW byte

CS.value(0)

# Enable MCP4921

spi.write(bytearray(buff))

# Send to SPI bus

CS.value(1)

# DIsable MCP4921

# # Main program # while True: for k in range(21): DAC(int(4095*Waveform[k]/3.3)) utime.sleep_ms(1)

Figure 6.39: Program: Arbitrary. Figure 6.40 shows the generated output waveform. Notice again that, as described earlier, the timing of the generated signal is not perfectly accurate and timer interrupts can be used to generate accurate output.

Figure 6.40: Output waveform.

6.6.6 Project 10: Generating a sinewave signal In this project we will generate a sinewave signal using the trigonometric function sin. The generated sinewave should have a peak-to-peak amplitude of 1.4 V, a frequency of 50 Hz, and an offset of 1 V. The block diagram and circuit diagram are as in Figure 6.26 and Figure 6.27, respectively.

● 158

Chapter 6 • Amateur Radio Hardware-based Projects

Program listing: Since the required frequency is 50 Hz, the period is 20 ms or 20,000 μs. If we assume that the sinewave consists of 100 samples, then each sample must be output at 20,000 / 100 = 200 μs. The sine function has the following format:

Offset + PeaktoPeak / 2 × sin(2 × π × Count / T)

where T is the period of the waveform and is equal to 100 samples. Count is a variable that ranges from 0 to 100 and is incremented by 1, PeaktoPeak is the peak-to-peak amplitude, and Offset is the DC offset. This is necessary because the sinewave has negative values, but the DAC only outputs positive values and therefore we have to shift the sinewave up by a DC offset. The sum of Offset and Amplitude voltage must not be greater than +3.3 V which is the maximum output voltage that the DAC can deliver i.e.:

Offset + PeaktoPeak > 8) & 0x0F

# HIGH byte

buff[0] = buff[0] + 0x30 buff[1] = data & 0xFF

# LOW byte

CS.value(0)

# Enable MCP4921

spi.write(bytearray(buff))

# Send to SPI bus

CS.value(1) # # Main program # sins=[0]*101 for i in range (101):

● 160

# DIsable MCP4921

Chapter 6 • Amateur Radio Hardware-based Projects

sins[i] = ReqDCoffset+PeaktoPeak/2 + PeaktoPeak/2 * math.sin(R*i) while True: for k in range(101): value = sins[k] DAC(int(value)) utime.sleep_us(200)

Figure 6.41: Program: Sine. Figure 6.42 shows the generated output waveform. Here, the horizontal axis was 20 ms / division and the vertical axis was 1 V/ division. The offset and the peak-to-peak amplitude of the waveform are correct but as described earlier, the timing of the generated signal is not perfectly accurate and timer interrupts may be used to generate accurate output.

Figure 6.42: Output waveform.

6.6.7 Project 11: Generating an accurate sinewave signal using timer interrupts In this project, we will generate an accurate sinewave signal using timer interrupts. Here, the required peak-to-peak amplitude is 1.4 V, the required offset is 1 V, and the required frequency is 50 Hz (period = 20 ms). In this project, we will take 50 samples instead of 100, so that the duration of each sample is 400 μs. In this program a timer interrupt is configured with the callback function of DAC and frequency of 2500 Hz (i.e., 400 μs each call). Inside function DAC, the data samples are indexed by variable k which is incremented at each interrupt. These samples are then output by the DAC. Figure 6.43 shows the program listing (Program: Sineint).

● 161

Raspberry Pi Pico for Radio Amateurs

#---------------------------------------------------------#

GENERATE SINE WAVEFORM

#

======================

# # In this project a MCP4921 type DAC chip is connected to the # Raspberry Pi Pico.The program generates a sine waveform with # the specifications given in the text # # This program uses timer interrupts for accurate timings # # Author: Dogan Ibrahim # File

: Sineint.py

# Date

: August 2021

#-----------------------------------------------------------from machine import Pin, SPI, Timer import utime import math tim = Timer() spi_sck = Pin(2)

# SCK pin at GP2

spi_tx = Pin(3)

# TX pin at GP3

spi_rx = Pin(0)

# RX pin at GP0 (not used)

spi = SPI(0,sck=spi_sck,mosi=spi_tx,miso=spi_rx,baudrate=100000) CS = Pin(16, Pin.OUT)

# CS

CS.value(1) # Disable chip R = 2 * 3.14159/50 T = 100 Conv = 4095.0 / 3.3 PeaktoPeak = 1.4 * Conv

# 1.4V

ReqDCoffset = 1.0 * Conv

# 1.6V

k = 0 def DAC(timer): global k, CS, sins buff = [0, 0] k = k + 1 if k == 50: k = 0 data = int(sins[k]) buff[0] = (data >> 8) & 0x0F

# HIGH byte

buff[0] = buff[0] + 0x30 buff[1] = data & 0xFF

# LOW byte

CS.value(0)

# Enable MCP4921

● 162

Chapter 6 • Amateur Radio Hardware-based Projects

spi.write(bytearray(buff)) # Send to SPI bus CS.value(1)

# DIsable MCP4921

# # Main program # sins=[0]*101 for i in range (101): sins[i] = ReqDCoffset+PeaktoPeak/2 + PeaktoPeak/2 * math.sin(R*i) tim.init(freq=2500, mode = Timer.PERIODIC, callback = DAC)

Figure 6.43: Program: Sineint. Figure 6.44 shows the output waveform. Here, the horizontal axis was 10 ms / division and the vertical axis was 1 V / division. It is clear that the period of the waveform is exactly 20 s as required, the offset is 1 V, and the peak-to-peak amplitude is 1.4 V.

Figure 6.44: Output waveform.

6.7 Waveform generation — using hardware In some applications you may want to generate accurate waveforms. In this section we will be using a programmable signal generator module to generate accurate sinewave and squarewave signals.

● 163

Raspberry Pi Pico for Radio Amateurs

6.7.1 Project 12: Fixed-frequency waveform generator We will be using the popular AD9850 signal generator module together with the Raspberry Pi Pico. The AD9850 module (Figure 6.45) is a dual sine- and square-waveform generator with the following features: • 0–40 MHz sine wave output • 0–1 MHz square wave output • 3.3 V or 5 V operation • 125 MHz on-board timing crystal • On-chip 10 bit DAC • Serial or parallel programming data • 60 mA operating current

Figure 6.45: AD9850 module. The AD9850's circuit architecture allows the generation of output frequencies of up to onehalf the reference clock frequency (or 62.5 MHz). The device also provides five bits of digitally-controlled phase modulation, which enables phase shifting of its output in increments of 180°, 90°, 45°, 22.5°,11.25°, and any combination thereof. In this project we will be generating a 1kHz sine wave as an example. Before using the AD9850 in a project, we need to know how to program it, and this is described briefly in the following sections (more information on the AD9850 can be obtained from the manufacturers' data sheet at:  https://www.analog.com/media/en/technical-documentation/data-sheets/ ad9850.pdf) Figure 6.46 shows the AD9850's pinout.

● 164

Chapter 6 • Amateur Radio Hardware-based Projects

Figure 6.46: AD9850 module pin layout. The pin definitions are: VCC: supply voltage (3.3 V or 5 V) GND: supply ground W_CLK: load word clock (used to load parallel or serial frequency/phase words) FQ_UD: frequency update (the frequency or phase is updated on rising edge of this pin) DATA: serial load pin RESET: master reset pin (HIGH to reset to clear all registers) D0-D7: parallel data input (for loading 32-bit frequency and 8-bit phase/control word) Square Wave Output1: squarewave output 1 (comparator output) Square Wave Output2: squarewave output 2 (comparator complement output) Sine Wave Output1: analog sinewave output 1 (DAC output) Sine Wave Output2: analog sinewave output 2 (DAC complement output) The on-board potentiometer is used to set the duty cycle of the square waveform. The AD9850 can be loaded either in parallel or in serial form. In this project we will be using the serial mode. Figure 6.47 shows the block diagram of the project. The sine output1 of the module is connected to the oscilloscope.

● 165

Raspberry Pi Pico for Radio Amateurs

Figure 6.47: Block diagram of the project. The circuit diagram of the project is shown in Figure 6.48. The following connections are made between the Raspberry Pi Pico and the AD9850 module: AD9850 module Raspberry Pi Pico FQ_UD GP10 (pin 14) W_CLK GP11 (pin 15) RESET GP12 (pin 16) DATA GP13 (pin 17)

Figure 6.48: Circuit diagram of the project. The relationship between the output frequency, reference clock, and tuning word of the AD9850 is determined by the following formula: Fout = ΔPhase × REFCLOCK / 232 or

ΔPhase = Fout × 232 /REFCLOCK

where Fout is the output frequency in MHz, ΔPhase is the value of the 32-bit tuning word, and REFCLOCK is the reference clock in MHz. The output sine wave is an analog signal output by a 10-bit DAC. Notice that 232 = 4,294,967,296.

● 166

Chapter 6 • Amateur Radio Hardware-based Projects

The AD9850 contains a 40-bit register consisting of the 32-bit frequency control word, 5-bit phase modulation word, and the power-down function. In this project, the register is loaded in serial fashion. In this mode, the rising edge of W_CLK shifts the 1-bit data on pin D7 (DATA) through the 40 bits of programming information. After shifting 40 bits, an FQ_UD pulse is required to update the output frequency (or phase). The serial mode is enabled by the following sequence (see Data Sheet page 12, Figure 10): • Pulse RESET • Pulse W_CLK • Pulse FQ_UD The 40-bit serial data is loaded as follows: • Send bit • Send bit • Send bit • ………. • ………. • Send bit • Send bit • Send bit • Send bit • Send bit • Send bit • Send bit • Send bit • Send bit • Send bit

0 - frequency (LSB) 1 - frequency 2 - frequency

31 32 33 34 35 36 37 38 38 39

- frequency (MSB) – Control (set to 0) – Control (set to 0) - power down - phase (LSB) - phase – phase – phase – phase – phase (MSB)

Figure 6.49 shows the program listing (Program: freqgen.py). At the beginning of the program, the connections of AD9850 pins FQ_UD, W_CLK, RESET, and DATA are set to 26, 19, 13, and 6, respectively, which are the GPIO pin names. These pins are configured as outputs, and all are cleared to 0 at the beginning of the program. The program consists of a number of functions as described below: SendPulse: This function sends a HIGH-LOW logic signals to the pin specified in its argument GPIOpin. SendByte: This function receives a byte as its argument. Then a loop is formed to send the 8 bits of this byte to serial input DATA. A pulse is sent to W_CLK after sending a bit. SetSerialMode: This function puts the AD9850 into serial mode by pulsing pins RESET, W_CLK, and FQ_UD.

● 167

Raspberry Pi Pico for Radio Amateurs

LoadFrequency: This function receives the required frequency as its argument. Then the tuning word is calculated using the formula described earlier in this section and is stored in variable f. Then a 'for' loop is formed to iterate 4 times. The LOW byte of f is then sent to function SendByte enabling its 8 bits to be sent to the serial input. Variable f is then shifted-right 8 times so that the next higher byte is serialized and sent to function SendByte. This process is repeated for the 4 bytes, making a total of 32 bits. Then, the remaining 8 bits are sent as zeroes so that the two Control words are 0, and also the phase bits are 0. The main program puts the AD9850 into serial mode, sets the required frequency as Hz (1000 Hz = 1 kHz), and loads the frequency into AD9850 by calling the function LoadFrequency. The program is terminated when Cntrl+C is entered from the PC keyboard. The AD9850 is stopped before terminating the program. #----------------------------------------------------------------#



FREQUENCY GENERATOR

#



===================

# # In this program an AD9850 module is connected to the Raspberry # Pi Pico. The program generates a sine wave with a frequency of 1kHz. # The on-board crystal of the AD9850 module is 125MHZ # # Author: Dogan Ibrahim # File

: freqgen.py

# Date

: August, 2021

#------------------------------------------------------------------from machine import Pin # # AD9850 module connections # FQ_UD = Pin(10, Pin.OUT)

# FQ_UD pin

W_CLK = Pin(11, Pin.OUT)

# W_CLK pin

RESET = Pin(12, Pin.OUT)

# RESET pin

DATA =

# DATA pin

Pin(13, Pin.OUT)

# # Set all outputs to 0 at the beginning # FQ_UD.value(0) W_CLK.value(0) RESET.value(0) DATA.value(0) #

● 168

Chapter 6 • Amateur Radio Hardware-based Projects

# This function sends a pulse to the pin specified in the argument # def SendPulse(GPIOpin): GPIOpin.value(1) GPIOpin.value(0) return # # This function sends bits of a byte of data to the AD9850 module # def SendByte(DataByte): for k in range(0, 8):

# Do 8 times

p = DataByte & 0x01

# Get bit 0

DATA.value(p)

# Output it

SendPulse(W_CLK)

# Send clock

DataByte = DataByte >> 1

# Get next bit

return # # This function puts AD9850 module into serial mode # def SetSerialMode(): SendPulse(RESET)

# Pulse RESET

SendPulse(W_CLK)

# Pulse W_CLK

SendPulse(FQ_UD)

# Pulse FQ_UD

return # # This function loads the 40-bit data to the AD9850. 32-bit # frequency data is sent, then the power down bit is sent as 0, # two Control bits are sent as 0, and then the 5 phase bits are # sent as 0 # def LoadFrequency(frequency): f = int(frequency * 4294967296 / 125000000) # See book for p in range(0, 4):

# Do 4 times

SendByte(f & 0xFF)

# Send Low byte

f = f >> 8

# Get next byte

SendByte(0x00)

# Send remaining bits

SendPulse(FQ_UD)

# Terminate serial

return try: SetSerialMode()

# Select serial mode

RequiredFrequency = 1000

# required 1000Hz

● 169

Raspberry Pi Pico for Radio Amateurs

LoadFrequency(RequiredFrequency)

# Load register

while True:

# Wait forever...

pass

# ...until stopped

except KeyboardInterrupt:

# Keyboard Cntrl+C

SendPulse(RESET)

# Stop AD9850

Figure 6.49: Program: freqgen.py. Figure 6.50 shows the project built on a breadboard.

Figure 6.50: Project built on a breadboard. An example output waveform from the program is shown in Figure 6.51. As it can be seen from this figure, the frequency of the waveform is exactly 1 kHz as required. The output is measured from pin Sineoutput1. The peak-to-peak amplitude of the waveform was measured to be exactly 1 V.

● 170

Chapter 6 • Amateur Radio Hardware-based Projects

Figure 6.51: Example sinewave display obtained from the program. Figure 6.52 shows the squarewave output produced by the program, measured from the Squareoutput2 pin. The duty cycle of the waveform can be adjusted by the potentiometer. The amplitude of the waveform was measured to be 3.3 V.

Figure 6.52: Example squarewave display from the program.

6.7.2 Project 13: Generating waveforms with frequency-entry on keypad and LCD readout This project is similar to the earlier one but here a keypad and an I2C LCD are used to set the frequency of the waveform. This makes the project autonomous so that the Raspberry Pi Pico can be used on its own without having to use a PC to set the frequency of the waveform.

● 171

Raspberry Pi Pico for Radio Amateurs

Figure 6.53 shows the block diagram of the project.

Figure 6.53: Block diagram of the project. Keypad: There are several types of keypads that can be used in microcontroller-based projects. In this project a 4×4 keypad (Figure 6.54) is used. This keypad has keys for numbers 0 through 9, letters A, B, C, D, and signs * and #. The keypad is interfaced to the processor with 8 wires called R1–R4 and C1–C4, representing the rows (R) and columns (C), respectively of the keypad (see Figure 6.55).

Figure 6.54: 4×4 keypad.

● 172

Chapter 6 • Amateur Radio Hardware-based Projects

Figure 6.55: Circuit diagram of the 4×4 keypad interface. The operation of the keypad is quite simple: the columns are configured as outputs and the rows as inputs. The pressed key is identified by using column scanning. Here, a column is forced logic low while the other columns are held logic high. Then the state of each row is scanned and if a row is found to be low, then the key at the intersection of the row which is low, and this column is identified as the key pressed. This process is repeated for all the rows. Figure 6.56 shows the circuit diagram of the project. The I2C LCD is connected to the Raspberry Pi as in the previous projects using the LCD, where GPIO 2 and GPIO 3 are used as the SDA and SCL pins, respectively. The AD9850 module is connected as in the previous project. The 4×4 keypad is connected to the following GPIO pins of the Raspberry Pi Pico. The row pins are held high using the internal pull-up resistors to +3.3 V: Keypad pin Raspberry Pi pin R1 GP4 R2 GP5 R3 GP6 R4 GP7 C1 GP8 C2 GP9 C3 GP16 C4 GP17

● 173

Raspberry Pi Pico for Radio Amateurs

Figure 6.56: Circuit diagram of the project. Figure 6.57 shows the pin configuration of the 4×4 keypad used in the project.

Figure 6.57: Pin configuration of the 4×4 keypad. Test program Before writing the project program we will first of all develop the code to read keys from the keypad just to verify that the keypad hardware and software are working properly.

● 174

Chapter 6 • Amateur Radio Hardware-based Projects

The basic steps to read a key are as follows: Configure all columns as outputs Configure all rows as inputs Set all columns to 1 DO for all columns Set a column to 0 DO for all rows IF a row is 0 THEN Return the key at this column and row position ENDIF ENDDO ENDDO

Figure 6.58 shows the test program (program: keypad.py). At the beginning of the program the keypad keys are defined after importing the required modules to the program. The keypad row and columns connections are defined using lists ROWS and COLS, respectively. Columns are then configured as outputs and are set to 1. Similarly, the rows are configured as inputs. Function Get_Key reads the pressed key and returns it to the calling program. Two for loops are used in the function: the first loop selects the columns and sets them to 0 one after the other one. The second loop scans the rows and checks if a row is at 0. The main program calls the function and displays the pressed key on the screen. You should evaluate the keypad hardware and software by pressing various keys on the keypad and verifying that the correct key is displayed on the PC screen. #-------------------------------------------------------------#

KEYPAD TEST PROGRAM

#

===================

# # This program shows how the a keypad can be used to display # the pressed keys # # Author: Dogan Ibrahim # File

: keypad.py

# Date

: August 2021

#------------------------------------------------------------from machine import Pin import utime C = [0]*4 R = [0]*4 KEYPAD = [ # Keypad keys [1,2,3,"A"], [4,5,6,"B"], [7,8,9,"C"],

● 175

Raspberry Pi Pico for Radio Amateurs

["*",0,"#","D"]] ROWS = [4,5,6,7]

# Row pins

COLS = [8,9,16,17]

# Column pins

for i in range(4):

# Conf columns

C[i] = Pin(COLS[i], Pin.OUT) C[i].value(1) for j in range(4):

# Conf rows

R[j] = Pin(ROWS[j], Pin.IN, Pin.PULL_UP) # # This function reads a key from the keypad # def Get_Key(): while True: for j in range(4): C[j].value(0)

# Set col j to 0

for i in range(4):

# For all rows

if R[i].value() == 0: return (KEYPAD[i][j])

# Row is 0? # Return key

while R[i].value() == 0: pass C[j].value(1)

# Col back to 1

utime.sleep(0.05)

# Wait 0.05s

while True: key = Get_Key()

# Get a key

print(key)

# Display the key

utime.sleep(0.5)

Figure 6.58: Program: keypad.py. We are now ready to develop the program of this project. Figure 6.59 shows the program listing (program: keypadsig.py). In this program key D is assumed to be the ENTER key where all the inputs to the keypad must be terminated by pressing the ENTER key. At the beginning of the program the library modules used, get imported to the program. Then the keypad layout is defined. The columns of the keypad are configured as outputs and its rows are configured as inputs. Function Get_Key receives a key from the keypad and returns it to the main program. The AD9850 module part of the program is same as in the previous project.

● 176

Chapter 6 • Amateur Radio Hardware-based Projects

Inside the main program loop function Get_Key is called to get the key numbers entered by the user. Only keys 0 to 9 and key D are accepted by the program. Pressing any other key is ignored by the program. When key D is pressed, the program stores the entered frequency in variable Total which is then copied to variable frequency. After pressing the D key, the LCD displays OK to confirm that the entered frequency value is accepted by the program. After a delay of 5 seconds, the second row of the LCD is cleared so that it is ready to accept a new frequency value. As in the previous project, the AD9850 is put into serial mode and the user entered frequency is loaded so that the required waveform is generated. #--------------------------------------------------------------------------------#

FREQUENCY GENERATOR WITH KEYPAD AND LCD

#

=======================================

# # In this program the required frequency is entered from a keypad # in Hz. An LCD is used to display the entered frequency # # Author: Dogan Ibrahim # File

: keypadsig.py

# Date

: Sept 2021

#------------------------------------------------------------from machine import I2C, Pin import utime from pico_i2c_lcd import I2cLcd # # I2C LCD module connected to SDA1, SCL1 # i2c_lcd = I2C(id=1,scl=Pin(3),sda=Pin(2),freq=100000) lcd = I2cLcd(i2c_lcd, 0x27, 2, 16) C = [0]*4 R = [0]*4 KEYPAD = [

# Keypad keys

[1,2,3,"A"], [4,5,6,"B"], [7,8,9,"C"], ["*",0,"#","D"]] ROWS = [4,5,6,7]

# Row pins

COLS = [8,9,16,17]

# Column pins

for i in range(4):

# Conf columns

C[i] = Pin(COLS[i], Pin.OUT)

● 177

Raspberry Pi Pico for Radio Amateurs

C[i].value(1) for j in range(4):

# Conf rows

R[j] = Pin(ROWS[j], Pin.IN, Pin.PULL_UP) # # This function reads a key from the keypad # def Get_Key(): while True: for j in range(4): C[j].value(0)

# Set col j to 0

for i in range(4):

# For all rows

if R[i].value() == 0: return (KEYPAD[i][j])

# Row is 0? # Return key

while R[i].value() == 0: pass C[j].value(1)

# Col back to 1

utime.sleep(0.05)

# Wait 0.05s

# # ================ AD9850 functions =================== # # AD9850 module connections # FQ_UD = Pin(10, Pin.OUT)

# FQ_UD pin

W_CLK = Pin(11, Pin.OUT)

# W_CLK pin

RESET = Pin(12, Pin.OUT)

# RESET pin

DATA =

# DATA pin

Pin(13, Pin.OUT)

# # Set all outputs to 0 at the beginning # FQ_UD.value(0) W_CLK.value(0) RESET.value(0) DATA.value(0) # # This function sends a pulse to the pin specified in the argument # def SendPulse(GPIOpin): GPIOpin.value(1) GPIOpin.value(0) return

● 178

Chapter 6 • Amateur Radio Hardware-based Projects

# # This function sends bits of a byte of data to the AD9850 module # def SendByte(DataByte): for k in range(0, 8):

# Do 8 times

p = DataByte & 0x01

# Get bit 0

DATA.value(p)

# Output it

SendPulse(W_CLK)

# Send clock

DataByte = DataByte >> 1

# Get next bit

return # # This function puts AD9850 module into serial mode # def SetSerialMode(): SendPulse(RESET)

# Pulse RESET

SendPulse(W_CLK)

# Pulse W_CLK

SendPulse(FQ_UD)

# Pulse FQ_UD

return # # This function loads the 40-bit data to the AD9850. 32-bit # frequency data is sent, then the power down bit is sent as 0, # two Control bits are sent as 0, and then the 5 phase bits are # sent as 0 # def LoadFrequency(frequency): f = int(frequency * 4294967296 / 125000000) # See book for p in range(0, 4):

# Do 4 times

SendByte(f & 0xFF)

# Send Low byte

f = f >> 8

# Get next byte

SendByte(0x00)

# Send remaining bits

SendPulse(FQ_UD)

# Terminate serial

return Total = 0 lcd.clear() # Clear LCD lcd.move_to(0, 0)

# To (0,0)

lcd.putstr("Frequency (Hz):")

# Heading

lcd.move_to(0, 1)

# To (0,1)

try: while True: lcd.move_to(0, 1) flag = 0

● 179

Raspberry Pi Pico for Radio Amateurs

while flag == 0: key = Get_Key()

# Get a key

if key != "D":

# Is it ENTER?

if str(key) >= "0" and str(key) ':

# Increment by 0.1 MHz

frequency = frequency + 0.1 set_freq(frequency) utime.sleep(1) elif c == '> 8 Nlower = N

& 0xFF

buff[0] = Nupper buff[1] = Nlower buff[2] = 0xB0 buff[3] = 0x10 buff[4] = 0x00 i2c.writeto (address, bytearray(buff)) lcd.clear() lcd.move_to(0, 0) lcd.putstr("freq set to:") lcd.move_to(0, 1) lcd.putstr(str(freq)+" MHz") init() frequency = 101.4

# Starting frequency

first = 1 while True: if RATE.value() == 1:

# Check RATE

step = 1

# Step=1 MHz

else: step = 0.1 if first == 1:

# Step=0.1 MHz # First time

first = 0 frequency = 101.4

# Set to 101.4

set_freq(frequency) utime.sleep(1) while UP.value() == 1 and DOWN.value() == 1: pass

● 249

Raspberry Pi Pico for Radio Amateurs

if UP.value() == 0: frequency = frequency + step

# UP pressed # Increment freq

while UP.value() == 0: pass set_freq(frequency) utime.sleep(0.1) if DOWN.value() == 0: frequency = frequency - step

# Down pressed # Decrement freq

while DOWN.value() == 0: pass set_freq(frequency) utime.sleep(0.1)

Figure 6.123: Program: FMradioLcd.py. Using a loudspeaker As described in the previous project, an audio amplifier module can be connected to the project, with a loudspeaker and a volume control potentiometer to match. Battery operation Now that the project is independent of the PC, we might want to operate it with a battery. Perhaps the easiest option is to use a power bank used to charge mobile phones. Then, the Raspberry Pi Pico can be connected to the power pack using the micro USB cable. Auto boot When operating independent of the PC, we may want the radio program to start as soon as power is applied to the Raspberry Pi Pico. The auto boot mechanism is explained in Chapter 7 and is repeated here. All we have to do is to save our program FMradioLcd.py as main.py on the Raspberry Pi. Then, the radio program will start automatically whenever power is applied to the Raspberry Pi Pico. Radio case front panel layout A suitable front panel layout for our radio is shown in Figure 6.124. A block diagram of the components inside the case is shown in Figure 6.125.

● 250

Chapter 6 • Amateur Radio Hardware-based Projects

Figure 6.124: Suitable front panel layout.

Figure 6.125: Block diagram of our FM radio.

6.14.3 Project 28: FM radio using an LCD and rotary encoder This project is similar to the previous one but here a rotary encoder is used to set the frequency instead of a switch and two buttons. Setting the frequency with a rotary encoder is accurate and quite easy. Turning the encoder shaft by one click changes the frequency by 0.1 MHz. Figure 6.126 shows the block diagram of the project. The frequency settings are displayed on the LCD as the rotary encoder is turned.

● 251

Raspberry Pi Pico for Radio Amateurs

Figure 6.126: Block diagram of the project. The circuit diagram of the project is shown in Figure 6.127. The connections between the Raspberry Pi Pico and the external components are as follows: Raspberry Pi Pico GPIO Pin number Connected to SDA1 4 I2C LCD SDA SCL1 5 I2C LCD SCL SDA0 SCL0

GP6 GP7 GP8

1 I2C Radio SDA 2 I2C Radio SCL 9 10 11

CLK Rotary encoder DT Rotary encoder SW Rotary encoder

Figure 6.127: Circuit diagram of the project.

● 252

Chapter 6 • Amateur Radio Hardware-based Projects

Figure 6.128 shows the program listing (program: RadioRotary.py). At the beginning of the program, the modules used are imported, the I2C LCD connection is defined, and the text TEA5767 FM RADIO is displayed in the top row of the LCD. Then, the rotary encoder connections and the TEA5767 FM radio module connections are defined. Functions init() and set_freq() are as in the previous projects. The main program is executed in a loop-forever using a while statement. Inside this loop, the rotary encoder turnings are sensed, and the frequency is changed by 0.1 MHz at each click of the rotary encoder. The resulting frequency is sent to function set_freq() which then configures the radio module to be set to this frequency and receive broadcasts. Make sure that you connect the antenna and earphones to the TEA5767 radio module before evaluating the project. #----------------------------------------------------------------#

FM RADIO WITH LCD AND ROTARY ENCODER

#

====================================

# # This is an FM radio using the TEA5767 radio module. The module # operates with the I2C signals SDA and SCL, connected to SCL0 # and SDA0 of the Raspberry Pi Pico. Additionally, a rotary encoder # is connected that can be used to increase or decrease the frequency # in steps of 0.1 MHz. It is recommended to use an audio amplifier # to increase teh signal level so that a loudspeaker can be connected # to the circuit # # Author: Dogan Ibrahim # File

: RadioRotary.py

# Date

: Sept 2021

#------------------------------------------------------------------from machine import I2C, Pin from pico_i2c_lcd import I2cLcd import utime # # I2C LCD module connected to SDA1, SCL1 # i2c_lcd = I2C(id=1,scl=Pin(3),sda=Pin(2),freq=100000) lcd = I2cLcd(i2c_lcd, 0x27, 2, 16) # # Display heading message # lcd.clear() lcd.move_to(0, 0) lcd.putstr("TEA5767 FM RADIO") utime.sleep(3) buff = [0]*5

● 253

Raspberry Pi Pico for Radio Amateurs

# # Rotary encoder connections # CLK = Pin(6, Pin.IN)

# CLK pin

DT = Pin(7, Pin.IN)

# DT pin

SW = Pin(8, Pin.IN, Pin.PULL_UP)

# SW pin



# # TEA5767 Radio module connected to SDA0, SCL0 # i2c = machine.I2C(0, scl=Pin(1), sda=Pin(0), freq=100000) address = 0x60 # Address # # Initialize the TEA5767 # def init(): buff[0] = 0x80 i2c.writeto(address, bytearray(buff)) utime.sleep(0.2) # # This function sets the radio to required frequency # def set_freq(freq): N = int (4 * (freq * 1000000 + 225000) / 32768) Nupper = N >> 8 Nlower = N

& 0xFF

buff[0] = Nupper buff[1] = Nlower buff[2] = 0xB0 buff[3] = 0x10 buff[4] = 0x00 i2c.writeto (address, bytearray(buff)) lcd.clear() lcd.move_to(0, 0) lcd.putstr("freq set to:") lcd.move_to(0, 1) lcd.putstr(str(freq)+" MHz") init() frequency = 101.4 set_freq(frequency)

● 254

# Starting frequency

Chapter 6 • Amateur Radio Hardware-based Projects

flag = 1 ClkOldState = CLK.value()



# Get CLK state

# # Get the required frequency. Each click of the rotary encoder # increments or decrements the frequency by 0.1 MHz # while True: ClkState = CLK.value() DTState = DT.value() if ClkState != ClkOldState and ClkState == 1: if DTState != ClkState: frequency = frequency + 0.1 else: frequency = frequency - 0.1 set_freq(frequency) utime.sleep(0.1) ClkOldState = ClkState

Figure 6.128. Program: RadioRotary.py. Figure 6.129 shows the project built on a breadboard and is set to 101.4 MHz.

Figure 6.129: Project built on a breadboard. Complete Raspberry Pi Pico FM radio 1. Battery operation Now that the project is independent of the PC, you might want to operate it with a battery. Perhaps the easiest option is to use a power bank used to charge mobile phones. This allows the Raspberry Pi Pico to be connected to the power pack using the micro USB cable.

● 255

Raspberry Pi Pico for Radio Amateurs

2. Auto boot When operating independent of the PC, we may want the radio program to start as soon as power is applied to the Raspberry Pi Pico. The auto boot mechanism is explained in Chapter 7 and is repeated here. All we have to do is to save our program RadioRotary.py as main.py on the Raspberry Pi. Then, the radio program will start automatically whenever power is applied to the Raspberry Pi Pico. 3. Using an audio amplifier module As described in the previous project, an audio amplifier module will be required before the radio can be connected to a loudspeaker. As an example, you can use the audio amplifier shown in Figure 6.130. This amplifier conveniently has built-in volume control.

Figure 6.130: Audio amplifier module. 4. Radio case front panel layout A suitable front panel layout for our radio is shown in Figure 6.131. A block diagram of the components inside the case is shown in Figure 6.132.

Figure 6.131: Suggested front panel layout.

● 256

Chapter 6 • Amateur Radio Hardware-based Projects

Figure 6.132: Block diagram of our radio.

6.15 Project 29: Measure the frequency and duty cycle of a PWM waveform – screen display In this project, the frequency and duty cycle of a PWM waveform are measured and displayed on the screen. The PWM waveform whose frequency and duty cycle is to be measured is applied to port GP17 (pin 22). Be sure that the applied voltage is not greater than +3.3 V, otherwise you may damage the input circuitry of your Pico. Figure 6.133 shows the program listing (Program: MeasPWM). The program measures the Mark (i.e., logic 1) and Space (i.e., logic 0) timings of the PWM input waveform in microseconds. The duty cycle and the frequency are then calculated as follows:

Duty cycle (%) = 100 × Mark / (Mark + Space) Frequency (kHz) = 1000 / (Mark + Space) #---------------------------------------------------------#

MEASURE THE FREQUENCY AND DUTY CYCLE

#

====================================

# # In this project a PWM wave is applied to the Pico. The # frequency and duty cycle of this wave are measured and # displayed on the Thonny screen. # # Author: Dogan Ibrahim

● 257

Raspberry Pi Pico for Radio Amateurs

# File

: MeasFreq.py

# Date

: Sept 2021

#-----------------------------------------------------------from machine import Pin import utime PWMin = Pin(17, Pin.IN)

# PWM wave input

while True: # Do forever while True: if PWMin.value() == 1:

# Wait while 0

break Tmr1Strt = utime.ticks_cpu()



# Start timer 1

while True: if PWMin.value() == 0:

# Wait while 1

break Tmr1End = utime.ticks_cpu()

# End

while True: if PWMin.value() == 1:

# Wait while 0

break Tmr2End = utime.ticks_cpu()



# End

Mark = utime.ticks_diff(Tmr1End, Tmr1Strt) Space = utime.ticks_diff(Tmr2End, Tmr1End) duty = 100.0 * Mark / (Mark + Space) freqkHz = 1000.0 / (Mark + Space) print("Duty Cycle = %5.2f" % duty) print("Frequency (kHz) = ", freqkHz, "\n") utime.sleep(2)

Figure 6.133: Program: MeasPWM. Example output from the program is shown in Figure 6.134.

Figure 6.134: Example output.

● 258

Chapter 6 • Amateur Radio Hardware-based Projects

6.16 Project 30: Measure the frequency and duty cycle of a PWM waveform – LCD display In this project, the frequency and duty cycle of a PWM waveform are measured and displayed on the LCD. The PWM waveform whose frequency and duty cycle is to be measured is applied to port GP17 (pin 22) as in the previous project. Be sure that the voltage applied is not greater than +3.3 V, otherwise you may damage the input circuitry of your Pico. Figure 6.135 shows the program listing (program: MeasPWMLcd). The program measures the Mark (i.e., logic 1) and Space (i.e., logic 0) timings of the PWM input waveform in microseconds. The duty cycle and the frequency are then calculated as follows:

Duty cycle (%) = 100 × Mark / (Mark + Space) Frequency (kHz) = 1000 / (Mark + Space) #---------------------------------------------------------#

MEASURE THE FREQUENCY AND DUTY CYCLE - LCD OUTPUT

# ================================================= # # In this project a PWM wave is applied to the Pico. The # frequency and duty cycle of this wave are measured and # displayed on the LCD # # Author: Dogan Ibrahim # File

: MeasFreq.py

# Date

: Sept 2021

#-----------------------------------------------------------from machine import Pin, I2C from pico_i2c_lcd import I2cLcd import utime # # I2C LCD module connected to SDA1, SCL1 # i2c_lcd = I2C(id=1,scl=Pin(3),sda=Pin(2),freq=100000) lcd = I2cLcd(i2c_lcd, 0x27, 2, 16) PWMin = Pin(17, Pin.IN)

# PWM wave input

while True: # Do forever while True: if PWMin.value() == 1:

# Wait while 0

break Tmr1Strt = utime.ticks_cpu()



# Start timer 1

while True: if PWMin.value() == 0:

# Wait while 1

● 259

Raspberry Pi Pico for Radio Amateurs

break Tmr1End = utime.ticks_cpu()

# End

while True: if PWMin.value() == 1:

# Wait while 0

break Tmr2End = utime.ticks_cpu()



# End

Mark = utime.ticks_diff(Tmr1End, Tmr1Strt) Space = utime.ticks_diff(Tmr2End, Tmr1End) duty = 100.0 * Mark / (Mark + Space) freqkHz = 1000.0 / (Mark + Space) lcd.clear() lcd.move_to(0, 0) lcd.putstr("Duty(%)=" + str(duty)[:5]) lcd.move_to(0, 1) lcd.putstr("F(kHz) =" + str(freqkHz)[:7]) utime.sleep(2)

Figure 6.135: Program: MeasPWMLcd.

6.17 Raspberry Pi Pico Bluetooth interface There are applications where a radio amateur may want to access equipment remotely, for example, through the Bluetooth functionality of a mobile phone. The Raspberry Pi Pico has no built-in Bluetooth module. We have to use an external Bluetooth module to enable the Pico to communicate with other devices via the Bluetooth. One possibility may be to use a Raspberry Pi computer. Perhaps a cheaper option is to use a serial Bluetooth module, such as the HC-06. In the next section, we will develop a project and learn how to connect a HC-06 type low-cost Bluetooth module to our Raspberry Pi Pico.

6.17.1 Project 31: Controlling an LED from a smartphone using Bluetooth In this project we will be sending commands over the Bluetooth link from a smartphone to control an LED connected to the Raspberry Pi Pico (you could easily replace the LEDs with relays, for example, so that electrical devices can be controlled remotely). In this project, valid commands are:

L1 L0

Turn LED ON Turn LED OFF

The HC-06 Bluetooth module HC-06 is a low-cost popular 4-pin serially controlled module with the following pins (see Figure 6.136):

● 260

Chapter 6 • Amateur Radio Hardware-based Projects

Figure 6.136: The HC-06 Bluetooth module. The HC-06 is a serially controlled module, with the following basic specifications: • +3.3 V to +6 V operation • 30 mA unpaired current (10 mA matched current) • Built-in antenna • Band: 2.40 GHz – 2.48 GHz • Power level: +6 dBm • Default communication: 9600 baud, 8 data bits, no parity, 1 stop bit • Signal coverage: 30 feet • Safety feature: Authentication and encryption • Modulation mode: Gauss frequency shift keying Figure 6.137 shows the block diagram of the project.

Figure 6.137: Block diagram of the project. Figure 6.138 shows the project circuit diagram. The RXD and TXD pins of the Bluetooth module are connected to UART 0 pins GP0 (TX) and GP1 (RX) of the Raspberry Pi Pico, respectively. The LED is connected to GP16 (pin 21) through a 470-ohm current-limiting resistor.

● 261

Raspberry Pi Pico for Radio Amateurs

Figure 6.138: Circuit diagram of the project. The program listing of the project is shown in Figure 6.139 (program: BlueLED). At the beginning of the program, the hardware UART interface is set to baud rate 9600 (i.e., the default speed of the HC-06), the LED is configured as an output, and turned OFF. The remainder of the program runs in an endless loop. Inside this loop data (commands) are received from the Bluetooth device using the function call readline. The data read is stored in list buf. The program then controls the LED based on the received command. e.g., L1 turns the LED ON, L0 turns it OFF and so on. #---------------------------------------------------------#

BLUETOOTH COMMUNICATION

#

=======================

# # In this project a HC-06 type serial Bluetooth module and # and LED are connected to the Raspberry Pi Pico. The LED # is controlled by sending commands from a Bluetooth # compatible smart phone. # # Author: Dogan Ibrahim # File

: BlueLED.py

# Date

: Sept 2021

#-----------------------------------------------------------from machine import Pin, UART import utime uart = UART(0, baudrate=9600,rx=Pin(1),tx=Pin(0)) LED = Pin(16, Pin.OUT) LED.value(0)

● 262

Chapter 6 • Amateur Radio Hardware-based Projects

# # Main program loop. Receive a command and control the LED # while True: buf = uart.readline()

# Read data

dat = buf.decode('UTF-8')

# Decode

if dat[0] == 'L' and dat[1] == '1':

# L1?

LED.value(1) elif dat[0] == 'L' and dat[1] == '0': LED.value(0)

# LED ON # L0? # LED OFF

Figure 6.139: Program: BlueLED. Testing the program The program can be evaluated by using an Android smartphone to send commands through a Bluetooth communication interface. There are many freely available Bluetooth communication programs in the Play Store. The one chosen by the author was called the Bluetooth Controller by mightyIT ([email protected]) as shown in Figure 6.140. You should install this app on your Android smartphone so you can send commands to the development board.

Figure 6.140: Bluetooth Controller app. The steps to test the application are as follows: • Construct the project. • Download the program to your Raspberry Pi Pico. • Activate the Bluetooth Controller app on your mobile phone. • The app will look for nearby Bluetooth devices. Click on HC-06 once displayed on the smartphone screen (you may have to scan for devices). • You will now be asked to enter the password to pair the phone with the development board. Enter the default password e.g., 1234.

● 263

Raspberry Pi Pico for Radio Amateurs

• Start the Bluetooth app on your smartphone. Click the semicircle with an arrow located at the top right-hand side of the screen to connect to HC-06. • You should see a green colour dot at the top right hand side of the screen when a connection is made to HC-06. Also, HC-06 with its address (e.g., HC06 [98:D3:31:FB:5E:B6] should be displayed at the top left-hand side of the screen. • To turn the LED ON, enter command L1 and click Send ASCII. You should see the LED turning ON. Enter command L0 to turn OFF the LED. Figure 6.141 shows an example screen.

Figure 6.141: Example command to turn the LED ON. We can modify the program in Figure 6.139 by sending a confirmation to the smartphone when there is change in the LED status. The required modifications are shown below: while True: buf = uart.readline()

# Read data

dat = buf.decode('UTF-8')

# Decode

if dat[0] == 'L' and dat[1] == '1':

# L1?

LED.value(1)



# LED ON

uart.write("LED is ON")



# Send confirmation

elif dat[0] == 'L' and dat[1] == '0':

# L0?

LED.value(0) uart.write("LED is OFF")

# LED OFF

# Send confirmation

For example, as shown in Figure 6.142, the message LED is ON is displayed on the screen after the command L1 is sent.

● 264

Chapter 6 • Amateur Radio Hardware-based Projects

Figure 6.142: Example display with confirmation.

6.18 Project 32: Station security If you have a family with children around, you may want to restrict access to your radio station room for safety and security reasons. In this project we will develop an RFID-based security system to control an output device. e.g., a relay, a buzzer, an LED, etc. The relay, for example, can be the door unlocking relay or the station's main power supply relay. Only people with a valid RFID card will be able to operate the relay. In this project, the popular RC522 RFID controller is used (see Figure 6.143). This is a lowcost RFID module based on the MFRC522 chip. The module communicates at 13.56 MHz and has the following features: • +3.3 V supply voltage • 13-26 mA operating current • 3 cm reading range • SPI interface to host MCU • 10 Mbit/s data transfer rate • Size: 60 × 39 mm The reader unit consists of a Radio Frequency module and an antenna which generates a high-frequency electromagnetic field. The tag is usually a passive device, meaning it doesn't contain a battery. Instead, it contains a microchip that stores and processes information, and an antenna to receive and transmit a signal. To read the information encoded on a tag, it is placed in close proximity to the Reader (no need to be within direct line-ofsight of the reader). A Reader generates an electromagnetic field which causes electrons to

● 265

Raspberry Pi Pico for Radio Amateurs

move through the tag's antenna and subsequently power the chip. The powered chip inside the tag then responds by sending its stored information back to the reader in the form of a radio signal.

Figure 6.143: RC522 RFID controller card. The pin layout of the RC522 module is shown in Figure 6.144.

Figure 6.144: Pin layout of the RC522 module. RX/SDA/SS is the signal input for the SPI bus (also acts as serial data when I2C interface is enabled). SCK is the serial clock provided by the SPI bus master. MOSI is the SPI input to the RC522 module. TX/SCL/MISO is the slave out when SPI bus is used and acts as serial clock when I2C interface is enabled. IRQ is the interrupt pin that can be used to alert the MCU when a RFID tag comes close to the reader. GND is the power ground pin. RST is the Reset pin. The reader is in reset mode when this pin goes Low. This pin should be connected to +3.3 V for normal operation. VCC is the +3.3 V power supply pin

● 266

Chapter 6 • Amateur Radio Hardware-based Projects

Figure 6.145 shows the block diagram of the project. An active buzzer is used as the output device in this project.

Figure 6.145: Block diagram of the project. Raspberry Pi Pico includes several SPI bus pins. In this project the following connections are made between the RFID card reader and Raspberry Pi Pico: Raspberry Pi Pico pin RC522 pin GP2 (4) SCK (7) GP3 (5) MOSI (6) GP4 (6) MISO (5) GP0 (1) RST (2) GP1 (2) SS (8) The connections between the Raspberry Pi Pico and the RFID card reader are shown in the circuit diagram in Figure 6.146. In this project, a buzzer is connected as the output device. When the authorized RFID tag is put near the card reader, the buzzer sounds for 5 seconds and then stops. This behavior can easily be changed if required.

Figure 6.146: Circuit diagram of the project.

● 267

Raspberry Pi Pico for Radio Amateurs

Figure 6.147 shows the program listing (program: RFID). The standard RFID ISO/IEC 14443-A cards have an UID with a length of 4 bytes, so there are 4,200 million different UIDs. Although the RFID cards can store data, in this project we are only interested in the UID code of our card. When a card is held close to the reader, the 4-byte UID of the card is read and is compared with the expected hard-coded UID number in the program. If the two numbers match, the device connected to the output is activated (in this example the buzzer is activated) for 5 seconds. If the device for example is a door relay, the door will be opened! The program used in this project makes use of the library mfrc522.py developed by Stefan Wendler, who is the Copyright holder of this library (see link:

https://github.com/danjperron/micropython-mfrc522)

The program mfrc522.py is included in the .zip archive file for this book. You should copy this program to your Raspberry Pi Pico before you can use the program given in Figure 6.147. Click File  Open on your Thonny session and browse to file mfrc522. py. Then, save the file on your Raspberry Pi Pico making sure that the file extension .py is included in the filename before saving it. The program given in Figure 6.147 reads the UID number of your RFID tag. If the tag is authorized, then the buzzer is activated. The 4-byte decimal UID number of author's card was 49, 49, 57, 46. You can find the UID number of your own RFID tag by removing the comment characters (###) at the beginning of the print statement in the program. Then use these numbers in the if statement to authorize your RFID tag. You can authorize multiple tags as long as you modify the if statement or add additional if statements. #---------------------------------------------------------#

RFID CARD READER

#

================

# # In this project a RC522 type RFID card reader is connected # to Raspberry Pi Pico. The program demonstrates how an RFID # card can be read. Only the UID of teh card is read and if it # the authorized card then a buzzer connected to GP13 of Raspberry # Pi Pico is activated for 5 seconds. This buzzer is for only # for demonstration purposes only and could be replaced with a # relay if required # # Author: Dogan Ibrahim # File

: RFID.py

# Date

: Sept 2021

#-----------------------------------------------------------from machine import Pin

● 268

Chapter 6 • Amateur Radio Hardware-based Projects

from mfrc522 import MFRC522 import utime Buzzer = Pin(13, Pin.OUT) Buzzer.value(0) reader = MFRC522(spi_id=0,sck=2,miso=4,mosi=3,cs=1,rst=0) while True: reader.init() (stat, tag_type) = reader.request(reader.REQIDL) if stat == reader.OK: (stat, uid) = reader.SelectTagSN() ###print(uid) if uid[0]==49 and uid[1]==49 and uid[2]==57 and uid[3]==46: Buzzer.value(1) utime.sleep(5) Buzzer.value(0)

Figure 6.147: Program: RFID.py. Figure 6.148 shows the project built on a breadboard.

Figure 6.148: Project built on a breadboard.

● 269

Raspberry Pi Pico for Radio Amateurs

6.19 Project 33: Generating accurate squarewave signals using the Raspberry Pi Pico State Machines In this project, we will be using the Raspberry Pi Pico State Machines (SM) to generate accurate squarewave signals in the range 2 kHz to over 100 MHz. The RP2040 contains two programmable IO blocks with four state machines each, to control GPIOs and to transfer data. Each PIO block has one instruction memory with 32 instructions. Each state machine can also control any of the GPIO pins on the Pico. Programming a PIO instance is by means of assembly language and the program can be written using the Thonny editor. Nine instructions are supported by the State Machines: • in() • out() • push() • pull() • mov() • irq() • wait() • jmp() • set() Figure 6.149 shows the program listing (program: SquareSM.py). At the beginning of the program the required libraries are imported. The function executed in the program is called square and is preceded by a decorator which informs the Python interpreter that what comes next contains assembly language statements. The statements set(pins, 1) and set(pins, 0) set and reset the specified pin. The wrap_target() and wrap() functions create a loop. The user is prompted to enter the required frequency and the pin number where the frequency will be generated at. The minimum value of the frequency is 2 kHz. The State Machine is initialized with the following statement:

sm = rp2.StateMachine(0, square, freq=f*2, set_base=Pin(p))

where State Machine 0 is used, freq is the required frequency, and set_base is the pin number attached to this State Machine. Statement sm.active(1) starts the State Machine, while statement sm.active(0) stops the State Machine. #======================================================= #

ACCURATE SQUARE WAVE

#

====================

# # This program uses the Raspberry Pi Pico State Machines # to create accurate square wave signals in the range # 2 kHz to 133 MHz #

● 270

Chapter 6 • Amateur Radio Hardware-based Projects

# Author: Dogan Ibrahim # File

: SquareSM.py

# Date

: Sept 2021

#======================================================== from machine import Pin from rp2 import PIO, StateMachine, asm_pio import utime @asm_pio(set_init=PIO.OUT_LOW) def square(): wrap_target() set(pins, 1) set(pins, 0) wrap() f = 0 while f < 2000: f = int(input("Enter frequency in Hz (Min 2000): ")) if f < 2000: print("Minimum frequency is 2000 Hz...") print("") p = int(input("Enter pin number: ")) sm = rp2.StateMachine(0, square, freq=f*2, set_base=Pin(p)) sm.active(1) utime.sleep(10) sm.active(0)

Figure 6.149: Program: SquareSM.py. Further information on the Raspberry Pi State Machine and its commands can be obtained from the following link:

https://dernulleffekt.de/doku.php?id=raspberrypipico:pico_pio

6.20 Project 34: Using Wi-Fi with the Raspberry Pi Pico – Controlling an LED from a smartphone As a radio amateur we may want to control remote devices through our home WiFi router using our smartphones. For example, we may want to control relays, LEDs, motors, etc., remotely using our smartphones. In this project we will be sending commands over our home Wi-Fi link from a smartphone to control an LED (the LED can be replaced with a relay, for example, to control a device connected to the Raspberry Pi Pico. Valid commands are (command must be terminated with a newline):

● 271

Raspberry Pi Pico for Radio Amateurs

LON LOFF

Turn LED ON Turn LED OFF

The Raspberry Pi Pico has no built-in Wi-Fi module and as such it cannot be connected to a Wi-Fi network without interfacing an external Wi-Fi module to it. Perhaps the easiest and the cheapest way of providing Wi-Fi capability to the Pico is by using an ESP-01 processor board. This is a tiny board (see Figure 6.150), measuring only 2.7 × 1.2 cm, based on the ESP8266 processor chip, and costing around $3 USD. The ESP-01 has the following features: • Operating voltage: +3.3 V • Interface: using simple AT commands over serial port/UART • Integrated TCP/IP protocol stack. 802.11 b/g/n • No external components required

Figure 6.150: ESP-01 processor board. The ESP-01 communicates with the host processor through its TX and RX serial port pin. It is an 8-pin board with these pin names: VCC: +3.3 V power supply pin GND: Power supply ground GPIO0: I/O pin. This pin must be connected to +3.3 V for normal operation, and to GND for uploading firmware to the chip GPIO2: General purpose I/O pin RST: Reset pin. Must be connected to +3.3 V for normal operation CH_PD: Enable pin. Must be connected to +3.3 V for normal operation TX: Serial output pin RX: Serial input pin The ESP-01's pins are not standard breadboard compatible, and an adaptor is required if the board is to be mounted onto a breadboard (see Figure 6.151).

● 272

Chapter 6 • Amateur Radio Hardware-based Projects

Figure 6.151: ESP-01 breadboard adapter. Figure 6.152 shows the project's block diagram.

Figure 6.152: Block diagram of the project. Figure 6.153 shows the circuit diagram of the project. The Raspberry Pi Pico's UART 0 TX and RX pins are used to communicate with the ESP-01.

● 273

Raspberry Pi Pico for Radio Amateurs

Figure 6.153: Circuit diagram of the project. Figure 6.154 shows the program listing (program: PicoWiFi). Inside the setup routine, the serial communication speed is set to 115200 which is the default Baud rate for ESP-01, and the LED is configured as an output and turned OFF. Function ConnectToWiFi is called to connect to the local Wi-Fi router. AT commands are used to configure the ESP-01 to connect to the Wi-Fi router. The remainder of the program runs in an endless loop formed using a while statement. Inside this loop, data is received from the smartphone and the LED is controlled accordingly. Commands LON and LOFF turn the LED ON and OFF respectively. A data packet is received from the smartphone using the statement readline and its function. The function find looks for a substring in a string and returns a non-zero value if the substring is found. The reason for using the find function is because the data received from the mobile device is in the following format +ID0,n: data (e.g., +ID0,3:LON) where 0 is the link ID and n is the number of characters received. Using the function find we can easily search for the strings LON or LOFF in the received data packet. The function ConnectToWiFi sends the following commands to the ESP-01 to connect to the Wi-Fi: AT+RST AT+CWMODE AT+CWJAP AT+CIPMUX AT+CIFSR AT+CIPSTART

● 274

- reset ESP-01 - set ESP-01 mode (here it is set to Station mode) - set Wi-Fi SSID name and password - set connection mode (here it is set to multiple connection) - returns the IP address (not used here) - set TCP or UDP connection mode, destination IP address, and port number (here, UDP is used with port number set to 5000. The destination IP address is set to "0.0.0.0" so that any device can send data as long as port 5000 is used (you can change this to the IP address of your smartphone to receive data from your phone only).

Chapter 6 • Amateur Radio Hardware-based Projects

#---------------------------------------------------------#

USING WI-FI

#

===========

# # In this project a ESP-01 chip is connected to the Raspberry # Pi Pico. This chip is used to connect the Pico to the Wi-Fi # # Author: Dogan Ibrahim # File

: PicoWiFi.py

# Date

: Sept 2021

#-----------------------------------------------------------from machine import Pin, UART import utime uart = UART(0, baudrate=115200,rx=Pin(1),tx=Pin(0)) LED = Pin(16, Pin.OUT) LED.value(0) # # Send AT commands to ESP-01 to connect to local WI-Fi # def ConnectToWiFi(): uart.write("AT+RST\r\n") utime.sleep(5) uart.write("AT+CWMODE=1\r\n") utime.sleep(1) uart.write('''AT+CWJAP="BTHomeSpot-XNH","49345xyzpq"\r\n''') utime.sleep(5) uart.write("AT+CIPMUX=0\r\n") utime.sleep(3) uart.write('''AT+CIPSTART="UDP","0.0.0.0",5000,5000,2\r\n''') utime.sleep(3) ConnectToWiFi() # # Main program loop # while True: buf = uart.readline()

# Read data

if buf: dat = buf.decode('UTF-8')

# Decode

● 275

Raspberry Pi Pico for Radio Amateurs

n = dat.find("LON")

# Includes LON?

if n > 0: LED.value(1) n = dat.find("LOFF")

# LED ON # Includes OFF?

if n > 0: LED.value(0)

# LED OFF

Figure 6.154: Program: PicoWiFi. Notice that small delays are used after each command. Command AT+CWJAP requires a longer delay. The program can easily be modified such that the delays can be removed and the responses from the ESP-01 can be checked. This way, as soon as the correct response is received, the program can continue. You may have to hardware-reset the ESP-01 by powering it down and up again before you run the program. Testing the program The program can easily be evaluated using the PacketSender program (see Figure 6.155) on the PC or using a smartphone after installing a UDP apps.

Figure 6.155: Using the PacketSender to test the program. You should install a UDP Server app on your Android mobile phone before starting the test with the smartphone. There are many freely available UDP apps in the Play Store. The one installed and used in this project is called the UDP/TCP Widget by K.J.M as shown in Figure 6.156.

● 276

Chapter 6 • Amateur Radio Hardware-based Projects

Figure 6.156: UDP/TCP Widget app for Android. The steps to test the program are as follows: • Construct the circuit. • Download the program to your Raspberry Pi Pico. • Start the UDP/TCP Widget app on your mobile phone. • Click the gear symbol and set the Protocol to UDP, IP address to the IP address of your Raspberry Pi Pico (192.168.1.160 in author's Pico) and set the Port to 5000 as shown in Figure 6.157.

Figure 6.157: Configuring the app. • Click the MESSAGE menu item and select Text (UTF-8) as the Format and enter command LON to turn ON the LED. Select LF\n as the Terminator and click the OK symbol (check symbol), as shown in Figure 6.158.

● 277

Raspberry Pi Pico for Radio Amateurs

• Now, click the SEND button (Figure 6.159) to send the command to the Raspberry Pi Pico. You should see the message Packet Sent displayed at the top of your Android screen temporarily.

Figure 6.158: Command to turn ON the LED.

Figure 6.159: Click SEND to transmit the command. Notice that the IP address of the ESP-01 can be obtained by scanning all the devices on the local Wi-Fi router. For example, Android apps called Who Uses My WiFi – Network Scanner by Phuongpn can be used to see the IP addresses of all the devices connected to your router. The ESP-01 is listed as shown in Figure 6.160 (IP: 192.168.1.160), listed with the name Espressif.

● 278

Chapter 6 • Amateur Radio Hardware-based Projects

Figure 6.160: Finding the IP address of the ESP-01.

6.21 Project 35: Audio amplifier module with rotary encoder volume control One of the problems with potentiometer-type volume controls in audio amplifiers is that the potentiometer is a noisy device, and it becomes difficult to adjust the volume accurately using a potentiometer as it gets older. In this project we will use an audio amplifier module with a rotary encoder to adjust the volume. The audio amplifier module used in this project is the AudioAmp click (Figure 6.161), designed and manufactured by MikroElektronika (www.mikroe.com). This is a mono audio amplifier, based on Texas Instruments LM48100Q-Q1 Boomer Mono, 1.3-watt audio power amplifier IC. The module has one 3.5-mm input jack and next to it screw terminals for connecting output wires to a passive speaker. It has dual audio inputs that can be mixed/multiplexed to the device output. Each input path has its own independent, 32-step digital volume control. The mixer, volume control and device mode selection are controlled through the mikroBUS I2C interface. Fault detection is another important feature of the LM48100Q. It senses the load conditions, protecting the device during short-circuit events, as well as detecting open circuit conditions. The AudioAmp Click can work either from a 3.3 V or a 5 V power supply. There's an additional jumper for selecting the I2C address as well.

Figure 6.161: AudioAmp Click module. In this project, we will be using a rotary encoder to change the 32-step digital volume of the amplifier. Turning the rotary encoder by one click will change the volume by one step. The circuit diagram of the amplifier module is shown in Figure 6.162.

● 279

Raspberry Pi Pico for Radio Amateurs

Figure 6.162: Circuit diagram of the amplifier module. Communication with the MCU is through the I2C interface. The following pins of the amplifier module are used: Pin Description 1,2,3,4,5,6 No connection 7 +3.3 V 8 GND 9 GND 10 +5 V (not used) 11 SDA 12 SCL 13,14 No connection 15 INT (fault) 16 No connection

● 280

Chapter 6 • Amateur Radio Hardware-based Projects

Figure 6.163 shows the block diagram of the project. The circuit diagram of the project is shown in Figure 6.164. The interface between the external components and the Raspberry Pi Pico is as follows: Raspberry Pi Pico Device GP6 (9) CLK rotary encoder GP7 (10) DT rotary encoder GP8 (11) SW rotary encoder GND (3) GND +3.3 V (36) +3.3 V SDA1 (4) SCL1 (5) GND (8) +3.3 V (36)

SDA AudioAmp click (11) SCL AudioAmp click (12) GND (8) +3.3 V (7)

Figure 6.164: Circuit diagram of the project.

● 281

Raspberry Pi Pico for Radio Amateurs

Figure 6.165 shows the program listing (Program: RotaryVolume). At the beginning of the program, the I2C interface between the audio amplifier module and the Raspberry Pi Pico are defined. #----------------------------------------------------------------#

AUDIO AMPLIFIER WITH ROTARY ENCODER VOLUME CONTROL

#

==================================================

# # In this project an audio amplifier module is used. The volume # control of the amplifier is digital. A rotary encoder is used # to step through and change the volume control at every click # of the rotary encoder. Only Input 1 is used in this project # # Author: Dogan Ibrahim # File

: RotaryVolume.py

# Date

: Sept 2021

#------------------------------------------------------------------from machine import I2C, Pin import utime buff = [0]*2 ModeControl = 0

# Mode control addr

VolumeControl1 = 0x03

# Vol control 1 addr

# # I2C AudioAmp module connected to SDA1, SCL1 # i2c = I2C(id=1,scl=Pin(3),sda=Pin(2),freq=100000) address = 0x7C # # Rotary encoder connections # CLK = Pin(6, Pin.IN)

# CLK pin

DT = Pin(7, Pin.IN)

# DT pin

SW = Pin(8, Pin.IN, Pin.PULL_UP)

# SW pin



# # Set initial voluem to a low value # vol1 = 0x65 buff[0] = VolumeControl1 buff[1] = vol1 i2c.writeto(address, bytearray(buff)) utime.sleep(1)

● 282

# Initial volume

Chapter 6 • Amateur Radio Hardware-based Projects

buff[0] = ModeControl

# Mode control

buff[1] = 0x14

# Select IN1

i2c.writeto(address, bytearray(buff))

# Send to I2C

utime.sleep(1) ClkOldState = CLK.value()



# Get CLK state

# # Get the required volume control step. Each click of the rotary # encoder increments or decrements the volume control by 1 step # while True: ClkState = CLK.value() DTState = DT.value() if ClkState != ClkOldState and ClkState == 1: if DTState != ClkState: vol1 = vol1 + 1 if vol1 > 0x7F: vol1 = 0x7F buff[0] = VolumeControl1 buff[1] = vol1 i2c.writeto(address, bytearray(buff)) utime.sleep(0.1) else: vol1 = vol1 - 1 if vol1 < 0x60: vol1 = 0x60 buff[0] = VolumeControl1 buff[1] = vol1 i2c.writeto(address, bytearray(buff)) utime.sleep(0.1) buff[0] = ModeControl

# Mode control

buff[1] = 0x14

# Select IN1

i2c.writeto(address, bytearray(buff)) utime.sleep(0.1) ClkOldState = ClkState

Figure 6.165: Program: RotaryVolume. The default I2C address of the amplifier module is 0x7C. Then the interface between the rotary encoder and the Raspberry Pi gets defined. A shown in Table 6.4, the LM48100Q amplifier module is controlled with 4 registers. In this project we will be using Input 1 only. The important registers that we will be using are the Mode register (address 0) and Volume control1 register (address 3).

● 283

Raspberry Pi Pico for Radio Amateurs

The Mode register must be set as follows:

B4: This bit must be set to 1 to enable the amplifier B2: This bit must be set to 1 to enable Input 1

The volume control register consists of 32 steps (0 to 31) where each step up corresponds to a higher volume. The default value of the volume control is 0x60 which corresponds to zero volume. Its maximum value is 0x7F which corresponds to the highest volume of 32nd step: 01143210 Where '4321' are binary bits corresponding to the 32-step volume control values, with 011 00000 being the minimum volume (step 0) and 011 11111 being the maximum value (step 32) At the beginning of the program, the default volume control is set to 0x65 with the following code. The sound volume is then changed in steps at each click of the rotary encoder shaft: vol1 = 0x65 buff[0] = VolumeControl1 buff[1] = vol1 i2c.writeto(address, bytearray(buff)) utime.sleep(1)

Table 6.4: LM48100Q amplifier control registers. Figure 6.166 shows the project built on a breadboard.

● 284

Chapter 6 • Amateur Radio Hardware-based Projects

Figure 6.166: Project built on a breadboard. Note: The amplifier project given in this section can easily be used with the Pico FM Radio project described in section 6.11.

6.22 Project 36: Morse decoder Morse code is still used by many amateur radio operators. Although it is much more fun to decode the code manually by listening to it, there are many amateurs who prefer to use a computer to decode the code and have it displayed on an LCD or on a computer screen. In section 6.9 we learned how to generate Morse code using the Raspberry Pi Pico. There, the projects were about translating English text to Morse code and then sending the code to a buzzer connected to the Pico. We have also learned how to generate random code for training purposes. In this section we will develop a Morse decoder project which will receive audible code through a microphone and then translate the code into text and display it on the screen in real time. The program automatically adjusts to the transmission speed of the code. Just to review, the Morse code timing (i.e., the speed) is as follows: • Dit: 1 unit • Dah: 3 units • Character spacing between dit and dah of a character: 1 unit • Character spacing between the characters of a word: 3 units • Word spacing: 7 units

● 285

Raspberry Pi Pico for Radio Amateurs

The speed of a Morse code is specified by how many words per minute can be sent or received. In most Amateur radio exams candidates are expected to send and receive at least 12 words per minute. The word PARIS is used as the standard word when calculating the speed. This word consists of 50 units of time: P: A: R: I: S:

.--. .- .-. .. …

1 1 1 1 1

1 1 1 1 1

3 3 3 1 1

1 3 1 1 (3) (3) 1 1 (3) (3) 1 1 [7]

14 units 8 units 10 units 6 units 12 units

Where () is the inter-character time, and [] is the inter-word time. Notice that at the end of a character we do not insert a dot time but an inter-character time (3 units). Similarly, at the end of a word, we do not insert a dot time, but an inter-word time (7 units). Knowing the words per minute (wpm), we can calculate the Dit (or bit) time in seconds as follows:

Dit time = 60 / (50 × wpm)

Thus, for example, at 20 wpm, the basic Dit time is given by: 60 / (50 × 20) = 60 ms. The program receives Morse code as audio and estimates the Dit timing. The other timings are then automatically calculated, and the code is translated to text and displayed on LCD. Figure 6.167 shows the block diagram of the project. A microphone module ("Mic" Click Board) is used to receive the audible Morse code. The code is then sent to a tone decoder IC (LM567) which generates binary High and Low values based on the input tone. The output of the tone generator is connected to one GPIO pin of the Raspberry Pi Pico. The translated code is displayed on the PC screen.

Figure 6.167: Block diagram of the project. The microphone The "Mic Click" is a click board from www.mikroe.com that carries an SPQ0410HR5H-B surfacemount silicon microphone with maximum RF protection. The board is designed to run on a 3.3 V power supply. Using the SiSonic™ MEMS technology, the SPQ0410HR5H-B consists of

● 286

Chapter 6 • Amateur Radio Hardware-based Projects

an acoustic sensor, a low-noise input buffer, and an output amplifier. "MaxRF" protection prevents RF noise picked up by traces from getting into the microphone output. The basic features of the Mic Click board are: • Supply current: 120 μA (typical) • Sensitivity: –42 dBV/Pa • Signal to noise ratio: 59 dB(A) • Total harmonic distortion: 1% • Output impedance: 400 ohms • Direction: Omnidirectional Pin 1 is the output voltage. A +3.3 V supply must be connected to pin 7 of the board. The tone decoder Figure 6.168 shows pin layout of the LM567 tone decoder IC. The LM567 is a high-stability, low-frequency integrated phase-locked loop (PLL) decoder. Due to its good noise suppression ability and center frequency stability, it is widely used in the decoding of various communication equipment and the demodulation circuits for AM and FM. The chip is also used in circuits such as touchtone decoding, ultrasonic controls, precision oscillators, frequency monitoring and control, paging detectors, etc. The LM567 tone decoder is a device capable of detecting whether an input signal is within a selectable detection range. The device has an open-collector transistor output, so an external resistor is required to reach the appropriate logic levels. When the input signal is within the detection band, the device output changes to the LOW state. The internal free-running frequency of the VCO defines the center frequency of the detection band. An external RC filter is required to adjust this frequency. The bandwidth within which the device will detect the desired frequency depends on the capacitance at the loop filter terminal. Usually, a 1 µF capacitor is connected to this pin. Pin descriptions of the LM567 are shown in Table 6.5.

Figure 6.168: Pin layout of LM567.

● 287

Raspberry Pi Pico for Radio Amateurs

Table 6.5: LM567 pin descriptions. The LM567 has the following basic features: • Operating voltage: 4.5 V to 9.0 V • Quiescent power supply current: 7 mA (typical) • Active power supply current: 12 mA (typical) • Smallest detectable input voltage: 20 mVrms • Highest center frequency: 500 kHz • Center frequency stability: 35 ± 60 ppm/ºC • Output saturation voltage: 0.2 V (typical) • Switching speed: center frequency / 20 Circuit diagram Figure 6.169 shows the circuit diagram of the project. Pins 4 and 7 are connected to +5 V and GND of the Raspberry Pi Pico. Morse code audio input is applied to pin 3 through a 470nF capacitor. The output is open-collector style and taken from pin 7. The center frequency of the LM567 tone decoder is equal to the free-running frequency of the voltage-controlled oscillator. In order to set this frequency, external components should be added. The component values are given by:

Where, R1 = Timing Resistor at pin 5, C1 = Timing Capacitor at pin 6. Using a 10 kohm resistor in series with a 10 kohm potentiometer and 0.1 μF capacitor, the center frequency can take the following values as the potentiometer is varied: At 10 kohm At 5 kohm At 1 kohm At 0 kohm

● 288

Chapter 6 • Amateur Radio Hardware-based Projects

Then frequency range f0 = 500–800 Hz should be a viable choice with the potentiometer arm between full-travel and half-travel. To eliminate undesired signals that could trigger the output stage, a post-detection filter is featured in the LM567C. This filter consists of an internal 4.7 kohm resistor and an external capacitor. Although typically the external capacitor value is not critical, it is recommended to use at least twice the value of the loop filter capacitor. If the output filter capacitor value is too large, the turn-on and turn off-time of the output will present a delay until the voltage across this capacitor reaches the threshold level. The bandwidth depends on the capacitor connected to pin 2 (C2) and is given as a percentage of the center frequency, where (assuming Vi 5 * ditmax: flag = 1 break utime.sleep(0.01) TmrEnd = utime.ticks_ms() SpaceTime = utime.ticks_diff(TmrEnd, TmrStrt) MyNum = MyNum 2*ditmax: colcnt = colcnt + 1 if colcnt > 32:

# LCD full?

lcd.clear()

# Clear LCD

colcnt = 0

# Start new row

utime.sleep(0.005)

# Wait to clr

lcd.putstr(Morse[MyNum])

# Display text

MyNum = 1 if flag == 1: break

● 293

Raspberry Pi Pico for Radio Amateurs

Setup() while True: Decode()

Figure 6.171: Program: MorseDecoder. Testing the program The steps to test the program are: • Construct the hardware. • Apply power to the Raspberry Pi Pico. Make sure that the green LED on the Mic Click board is turned ON. Run the program (click the green button if using Thonny). Make sure that the text MORSE is displayed on the LCD for 2 seconds. If these do not happen, you should check your hardware before proceeding. • Use a Morse code audio generator program on your mobile phone. For example, the Morse Code Translator program, available on Internet (link: https://morsecode.world/international/translator.html) can be extremely helpful (see Figure 6.172)

Figure 6.172: Morse code translator program. • Click Configure and set it to 12 wpm, 800 Hz tone, and maximum volume of 100 as shown in Figure 6.173.

● 294

Chapter 6 • Amateur Radio Hardware-based Projects

Figure 6.173: Configuring the program. • Place your smartphone close to the Mic Click board microphone, type in some letters in window labelled Translate a Message. e.g., ABCDEFG (see Figure 6.174), and press Play. Turn the frequency potentiometer slowly until the LED starts flashing. The LED will flash as the Morse code is output on your smartphone speaker. After a while, the Morse code will be transformed into letters and displayed on the LCD. Notice that the first few letters will not be displayed as they will be used to set up the speed in the program. From then on, all the letters will be displayed correctly.

Figure 6.174: Enter some letters for testing.

● 295

Raspberry Pi Pico for Radio Amateurs

The program was tested at speeds up to 80 wpm. It was found that up to about 60 wpm the characters are received, transformed, and displayed correctly. Above 60 wpm most of the characters are displayed correctly, but occasionally errors occurred. It is recommended to keep the tone volume high and the audio output close to the Mic click board microphone. Figure 6.175 shows the project built on a breadboard. You may want to store the program as main.py (see Chapter 7) so that it runs automatically after reboot.

Figure 6.175: Project built on a breadboard.

6.23 Raspberry Pi Pico RTL-SDR Back in 2012 an undocumented feature of the RTL2832U chip was discovered which enabled it to be used as a general-purpose Software Defined Radio (SDR). With the development of hardware and software, these cheap "dongles" can now be used as sophisticated SDR receivers. For example, an RTL-SDR dongle can be connected to a Raspberry Pi and many interesting software packages can be downloaded to the Raspberry Pi. Without these dongles, such receivers having similar features would have costed hundreds or thousands of dollars. Some of the application areas of RTL-SDR dongles are: • Listening to air traffic control conversations • Tracking aircraft positions • Receiving meteorological transmissions • Listening to amateur radio bands • Listening to shortwave and FM radio • Listening to DAB broadcast transmissions • Receiving and decoding GPS signals

● 296

Chapter 6 • Amateur Radio Hardware-based Projects

• Decoding ham radio APRS packets • Developing a radio scanner • Watching analog broadcast TV • Using it as a spectrum analyzer • Using it as a receiver server • Listening to satellites • Scanning cordless phones and baby monitors • etc. The minimum requirements to use an RTL-SDR dongle are: • An RTL-SDR dongle device • A suitable antenna (some shipped with antennas) • A powerful computer (e.g., a Raspberry Pi 4) • RTL-SDR driver and application software (there are many and most are free) Depending on your requirements and applications, you may also need to use filters to improve the signal to noise ratio. RTL-SDR devices can work from about 24 MHz to over 1.7 GHz. The lower frequency range can be extended by using an upconverter device or by direct-sampling mode. The upconverter is connected to the antenna before the RTL-SDR device. Some upconverters operate at as low as several kHz. If the upconverter oscillator frequency is 125 MHz and we want to tune to 5 MHz, then we have to tune our receiver to 130 MHz. The direct-sampling mode requires a slight change to be made to the RTL-SDR hardware and the software, where a connection is made inside the hardware. Some RTL-SDR devices have a small hole on them so that a connection can be made by inserting a jumper wire, thus there is no need to open the device and do any soldering. The software should be configured so that the sampling mode is set to Direct Sampling. The RTL-SDR has 3.2 MHz bandwidth, 8-bit analog-to-digital converters (ADC), less than 4.5 dB noise figure and 75 ohm input impedance (i.e., not 50 ohms which is the impedance used in amateur radio. In general, the mismatch between the 75 ohm and 50 ohm is less than 0.2 dB). Because the RTL-SDR devices are cheap, they use 28.8 MHz crystal oscillators, and their clock accuracy may drift several kHz. Most popular RTL-SDR software packages have options in the form of ppm drift values for calibrating this drift in software. There are also spike noises in the form of harmonics at multiples of 28.8 MHz. These spikes can usually be observed in waterfall displays. For good reception and low noise, the RTL-SDR should be placed close to the antenna so that effectively the lossy coaxial cable is replaced with non-lossy USB cable. You should take care, however, that the length of the USB cable is not more than 5 meters for USB2.0 or 3 meters for USB3.0. If longer USB cables are required, then it is recommended to use USB hubs or USB repeater devices.

● 297

Raspberry Pi Pico for Radio Amateurs

The RTL-SDR dongles should be placed in metal enclosures in order to minimize external interferences and they should not be near power lines, motors, TVs, electrical appliances, or other equipment that may generate electromagnetic noise. Having a good antenna is also especially important while using your RTL-SDR. The cheap antenna normally delivered with the device is about 12-15 cm long and not generally suitable for radio amateur work. You should place this antenna over a metal surface with a radius of around 12-15 cm to make a quarter-wave antenna and improve the reception characteristics. RTL-SDR devices work perfectly on the powerful Raspberry Pi 4 type computers sporting a fast CPU, substantial amounts of memory, and USB ports required for the RTL-SDR devices. Unfortunately, because of the limitations of the Raspberry Pi Pico hardware and software, it is not possible to install RTL-SDR hardware and software on the Pico. At the time of writing this book, it was reported by radio amateur Luigi Cruz (link:

https://www.rtl-sdr.com/piccolosdr-a-simple-sdr-from-a-raspberry-pi-pico/

that the ADC on the Pico could be used as a simple direct-sampling SDR with a bandwidth of only 250 kHz. This is of course limited and its only possible to receive station up into the LF bands, and there are not that many signals there. Although an interesting project which demonstrated the idea, is not particularly useful in practice.

6.24 Project 37: Using the FS1000A 433 MHz transmitter/receiver pair The FS1000A transmitter and compatible receiver (XY-MK-5V) are very low-cost transmitter/receiver modules costing only a few dollars (see Figure 6.176). These are short distance transmitter/receiver modules that can be used for example in an amateur radio station to operate relays etc. The basic features of the transmitter module are: • Transmitting Frequency: 433.92 MHz, 315 MHz, 330 MHz • Operating Voltage: 3 V to 12 V • Transmitting Power: 10 mW to 40 mW; 16 dBm • Transmitting Range: 20 to 100 meters through walls & 500 meters max. in open area • Data Transfer Rate: