diff --git a/Package.swift b/Package.swift index c8a6836..2dd4468 100644 --- a/Package.swift +++ b/Package.swift @@ -13,13 +13,14 @@ let package = Package( ], dependencies: [ .package(url: "https://github.com/uraimo/SwiftyGPIO.git", from: "1.2.5"), + .package(url: "https://vato.ddns.net/gitlab/vato007/SwiftSerial.git", .branch("master")) ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. // Targets can depend on other targets in this package, and on products in packages which this package depends on. .target( name: "Swift2dCar", - dependencies: ["SwiftyGPIO"]), + dependencies: ["SwiftyGPIO", "SwiftSerial"]), .testTarget( name: "Swift2dCarTests", dependencies: ["Swift2dCar"]), diff --git a/Sources/Swift2dCar/Esp32ServoOutput.swift b/Sources/Swift2dCar/Esp32ServoOutput.swift new file mode 100644 index 0000000..07a255d --- /dev/null +++ b/Sources/Swift2dCar/Esp32ServoOutput.swift @@ -0,0 +1,85 @@ +// +// Esp32ServoOutput.swift +// +// +// Created by Michael Pivato on 9/9/20. +// + +import Foundation +import SwiftyGPIO +import SwiftSerial + +/** + This class implements PWMOutput from the SwiftyGPIO package to communicate over Serial with an ESP32 that is running + the sketch found in the esp32 subproject in picar: https://vato.ddns.net/gitlab/vato007/picar + */ +public class Esp32ServoOutput : PWMOutput { + private let serialPort: SerialPort + private let channel: UInt8 + private let pin: UInt8 + + public static let ESP32_RESOLUTION: UInt8 = 8 + + public init?(forChannel channel: UInt8, forPin pin: UInt8, onPort port: SerialPort) { + if channel < 0 || channel > 16 { + return nil + } + self.channel = channel + // TODO: Add checks for pin number, or make init private with enums for each pin. + self.pin = pin + self.serialPort = port + } + + public convenience init?(forChannel channel: UInt8, forPin pin: UInt8, onPort port: String) { + self.init(forChannel: channel, forPin: pin, onPort: SerialPort(path: port)) + } + + public func initPWM() { + do { + try serialPort.openPort() + serialPort.setSettings(receiveRate: .baud115200, transmitRate: .baud115200, minimumBytesToRead: 1) + let bytesWritten = try serialPort.writeData(Data([0, 1, channel, pin])) + if bytesWritten != 4 { + print("Wrote %d bytes, but should have written 4", bytesWritten) + } + + } catch { + print("Failed to init PWM") + } + } + + public func startPWM(period ns: Int, duty percent: Float) { + do { + // Scale to 1 byte range, which is the current resolution. + let bytesWritten = try serialPort.writeData(Data([channel, (UInt8)((percent / 100) * pow(2, Float(Esp32ServoOutput.ESP32_RESOLUTION)))])) + if bytesWritten != 2 { + print("Wrote %d bytes, but should have written 2", bytesWritten) + } + } catch { + print("Failed to start PWM") + } + } + + public func stopPWM() { + + } + + // Patterns not supported for now. + public func initPWMPattern(bytes count: Int, at frequency: Int, with resetDelay: Int, dutyzero: Int, dutyone: Int) { + + } + + public func sendDataWithPattern(values: [UInt8]) { + + } + + public func waitOnSendData() { + + } + + public func cleanupPattern() { + + } + + +} diff --git a/Sources/Swift2dCar/Servo.swift b/Sources/Swift2dCar/Servo.swift index 0cf2128..0b55de5 100644 --- a/Sources/Swift2dCar/Servo.swift +++ b/Sources/Swift2dCar/Servo.swift @@ -92,7 +92,7 @@ open class PWMHardwareServo : Servo{ self.device = pin self.device.initPWM() self.internalValue = initialValue - self.device.startPWM(period: Int(self.frameWidth), duty: self.minDc + self.dcRange * ((internalValue - self.minValue) / self.valueRange) * 100) + self.value = initialValue } public func min(){