Swift Raspberry Pi Pico & Drone project

Hi!

Based of led raspberry pi pico example. I decided to build from it and create a drone project.

So far I’m at the stage here. Where I have 2x servos and engine control.
I’m Adding IR with remote to be able to manipulate elevon left/right and engine.

All powered by 4x AA batteries.
3d printed model.

If there is interest for it I might share model I’ve used and more information. Like photos etc.

I had a little break but will be back on it soon!

In the mean time, please check out the code and give me any feedback you might have.

All this is compiled with Swift 5.9, have not had a chance to update it to 6.x yet. but will do!

9 Likes

This is very cool! If you're up for it, feel free to push a PR to include this project in the community examples linked from swift-embedded-examples.

1 Like

That is awesome and inspiring :star_struck: Thanks for sharing!

1 Like

Very nice! One thing I’m hoping to see over time is an ecosystem of Swift packages that support various boards. The RP2040 and Support targets from the swift embedded examples that you are using is a great example. We’ll have to think of ways to make that easier to do.

The RP2040 example files are a great start. I simply used the templated and moved from there.

Some of the changes I did to it:

- GPIO writes now map each bit to the intended pin (bit 3 no longer toggles pin 0), fixing incorrect patterns when writing full bytes to multiple pins. See write(_:to:) in Sources/RP2040/HAL/Digital.swift.

- setMode configures pads for inputs (with optional pull-up/down) and outputs with selectable drive strengths, ensuring pins are put in a safe, explicit state before use. The new cases set pulls, input/output enables, slew rate, and drive strength in Sources/RP2040/HAL/Digital.swift:

public func setMode(_ mode: PinMode, pin: some DigitalPin) {

hardware.ioBank0.gpioControl\[idx\].modify { $0.functionSelection = .sio0 }

switch mode {

case .inputPullup: hardware.padsBank0.gpio[idx].modify { $0.pullUpEnable = true; $0.outputDisable = true }

case .output8mA: hardware.padsBank0.gpio[idx].modify { $0.outputDisable = false; $0.driveStrength = .level8mA }

// …other input/output variants

}

}

- Added digitalRead and the underlying SIO gpioIn accessor so firmware can read logic levels from GPIOs instead of only driving them. References: Sources/RP2040/HAL/Digital.swift and Sources/RP2040/Hardware/SIO.swift.

public var gpioIn: UInt32 {

RP2040Hardware.read(UInt32.self, from: unsafeAddress, offset: 0x0004)

}

public func digitalRead(pin: some DigitalPin) -> Bool {

((hardware.sio.gpioIn >> pin.rawValue) & 1) != 0

}

- The monotonic timer (now) is public and sleep(forMilliseconds:) now delegates to the microsecond sleep helper, giving more accurate, timer-based delays than the previous fixed loop. See Sources/RP2040/HAL/Time.swift:

public var now: UInt64 { /* awh/awl latch */ }

public func sleep(forMilliseconds ms: Int) {

    if ms > 0 { sleep(forMicroseconds: UInt64(ms) * 1_000) }

}

I will add state machine diagram and sequence diagram for the main loop and a control loop for input output.

Right now project doesn’t bind IR to control servos nor engines. It is all done via the breadboard buttons.

But WIP. Idea is to learn as I go :slight_smile:
Community support and feedback is very important.

To be done yet:

  1. IR support
  2. Main Loop
  3. Bind input output control loop
  4. Add failsafe for IR to shutdown it (so it won’t fly away) in case of no IR control input in X number of seconds. As we know sun kills red light, but in theory I should have 5-20m range lol

Stay tuned!

Assembling my little guy :backhand_index_pointing_down:t3:

Cheers!

Thanks to you all, for all the warm words! Bumps my motivation! :slight_smile:

7 Likes