DEV Community

Cover image for Self-Aligning Dish in Rust: Introduction
Ian Ndeda
Ian Ndeda

Posted on • Edited on

Self-Aligning Dish in Rust: Introduction

Rust is a relatively new programming language with a lot of potential in systems programming. Its memory safety makes it a particularly useful choice in building secure software.

In the upcoming posts, we will be using Rust to program a Raspberry Pi Pico microcontroller. Beginner-level skills in Rust are therefore necessary. The Rust Book is an excellent resource for both learning and as a reference.

Table of Contents

Microcontroller Access

A programmer can interact with a microcontroller by manipulating the data in its memory locations/registers. The various peripherals are configured and operated through these registers. If we wanted to light a connected LED, for example, we would have to access and operate on the particular bit responsible for that input/output pin.

There are a number of ways to access these registers. The ‘lowest-level’ method is by conducting bitwise operations on that bit. This is the least abstract method because we directly read/write to a register. An example is shown below:

const SIO_GPIO_OUT: u32 = 0xD0000010;// GPIO output address

unsafe {
    *(SIO_GPIO_OUT as *mut u32) | 1 < 25 ;// set bit 25
}
Enter fullscreen mode Exit fullscreen mode

The other way is to use HALs: hardware abstraction layers. These are libraries developed to implement the traits in the embedded-hal crate. An example is the rp2040-hal for the Raspberry Pi Pico. They allow a higher level of abstraction during programming, resulting in more user-friendly access to the microcontroller.

// pin set up here

pin.set_high();
Enter fullscreen mode Exit fullscreen mode

Under the hood, these HALs ultimately perform direct memory reading/writing, as in the previous case.

Rust also provides PACs (peripheral access crates), which are something of a halfway house between HALs and direct access. It is low-level enough to see what is happening on the hardware, but with a thin layer of abstraction over the read/write operations.

// peripherals: sio etc set up here

sio.as_mut().unwrap().gpio_out().modify(|r, w| unsafe { w.bits(r.gpio_out().bits() | 1 << 25)});// set bit 25 
Enter fullscreen mode Exit fullscreen mode

We will be using PACs in this project.

Flowchart

We are going to build a simple model for a self-aligning satellite dish, i.e., a dish that tracks a selected satellite in the geostationary orbit. 

We want to be able to operate the system in either auto or manual modes. In auto mode, the dish will seek the satellite out and align towards it by itself. Any deviation from the aligned position will be immediately corrected. 

In manual mode, we will be able to align the dish on our own by panning and tilting it to face our desired direction. This functionality is useful when you need to fine-tune the system after an initial auto-alignment.

The general flow of our program will be fairly simple, as shown in the following flowchart:

dish-flowchart

In our model, we will use a pan-tilt (PTZ) to simulate the positioning of the dish. Servo motors will be used to actuate the kit. We will also use an electronic compass to get the general system's magnetic headings, a GPS module to acquire its coordinates, and a Bluetooth module for remote communication.

We have to accomplish the following for our project to work:

  • Listen for commands
  • Acquire GPS coordinates
  • Calculate look angles
  • Align the dish and
  • Blink every second to indicate the program is running.

We will begin implementing the various project components in the next post.

Top comments (0)