// Raspberry Pi LPC1114 I/O Processor Expansion Board SPI Agent Firmware // Pulse Width Modulator output services // Copyright (C)2014-2018, Philip Munts, President, Munts AM Corp. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. using System; namespace SPIAgent { /// /// The PWM (Pulse With Modulation) class implements LPC1114 PWM output services. /// public class PWM: IO.Interfaces.PWM.Output { /// /// The number of available PWM output channels. /// public const int MIN_CHANNELS = 4; /// /// The minimum allowed PWM frequency is 50 Hz. /// public const int MIN_FREQUENCY = 50; // Hertz /// /// The maximum allowed PWM frequency is 50,000 Hz. /// public const int MAX_FREQUENCY = 50000; // Hertz /// /// The minimum allowed PWM duty cycle is 0.0 percent. /// public const double MIN_DUTYCYCLE = 0.0F; // Percent /// /// The maximum allowed PWM duty cycle is 100.0 percent. /// public const double MAX_DUTYCYCLE = 100.0F; // Percent private ITransport mytransport; private int mypin; private SPIAGENT_COMMAND_MSG_t cmd; private SPIAGENT_RESPONSE_MSG_t resp; /// /// LPC1114 PWM output object constructor. /// /// SPI Agent Firmware transport object. /// LPC1114 PWM output pin number. /// Allowed values are LPC1114_PWM1 through LPC1114_PWM4. /// PWM pulse frequency. /// Allowed values are 50 to 50000 Hz. public PWM(ITransport spiagent, int pin, int frequency = 100) { // Validate parameters if (spiagent == null) { throw new NullReferenceException("SPI Agent Firmware transport handle is null"); } if (!Pins.IS_PWM(pin)) { throw new ArgumentException("PWM pin number is invalid"); } if (frequency < MIN_FREQUENCY) { throw new ArgumentException("PWM pulse frequency is invalid"); } if (frequency > MAX_FREQUENCY) { throw new ArgumentException("PWM pulse frequency is invalid"); } cmd = new SPIAGENT_COMMAND_MSG_t(); resp = new SPIAGENT_RESPONSE_MSG_t(); // Build the command message cmd.command = (int)Commands.SPIAGENT_CMD_CONFIGURE_PWM_OUTPUT; cmd.pin = pin; cmd.data = frequency; // Dispatch the command spiagent.Command(cmd, ref resp); // Handle errors if (resp.error != 0) { throw new SPIAgent_Exception("SPI Agent Firmware returned error " + ((errno)resp.error).ToString()); } mytransport = spiagent; mypin = pin; } /// /// This write-only property sets this PWM output's duty cycle. /// Allowed values are 0.0 through 100.0 percent (from almost always off to almost always on). /// public double dutycycle { set { // Validate parameters if ((value < MIN_DUTYCYCLE) || (value > MAX_DUTYCYCLE)) { throw new ArgumentException("Invalid duty cycle value"); } // Build the command message cmd.command = (int)Commands.SPIAGENT_CMD_PUT_PWM; cmd.pin = mypin; cmd.data = (int)Math.Round(655.35F * value); // Dispatch the command mytransport.Command(cmd, ref resp); // Handle errors if (resp.error != 0) { throw new SPIAgent_Exception("SPI Agent Firmware returned error " + ((errno)resp.error).ToString()); } } } } /// /// The Servo class implements LPC1114 RC servo output services. /// public class Servo : PWM, IO.Interfaces.Servo.Output { private int freq = 50; /// /// The minimum servo position is -1.0. /// public const double SERVO_MIN_POSITION = -1.0F; /// /// The midpoint/neutral/null/zero servo position is 0.0. /// public const double SERVO_NEUTRAL_POSITION = 1.0F; /// /// The maximum servo position is 1.0. /// public const double SERVO_MAX_POSITION = 1.0F; /// /// LPC1114 RC servo output object constructor. /// /// SPI Agent Firmware transport object. /// LPC1114 PWM output pin number. /// Allowed values are LPC1114_PWM1 through LPC1114_PWM4. /// PWM pulse frequency. /// Allowed values are 50 to 400 Hz. public Servo(ITransport spiagent, int pin, int frequency = 50) : base(spiagent, pin, frequency) { // Check the PWM frequency if (frequency > 400) { throw new ArgumentException("PWM frequency is too high for servos"); } freq = frequency; // Move servo to the neutral position position = SERVO_NEUTRAL_POSITION; } /// /// This write-only property sets this servo output's position. /// Allowed values are -1.0 through 1.0 (normalized deflection from the null position). /// public double position { set { // Validate parameters if ((value < SERVO_MIN_POSITION) || (value > SERVO_MAX_POSITION)) { throw new ArgumentException("Invalid servo position value"); } dutycycle = (0.5E-1F * value + 1.5E-1F)*freq; } } } /// /// The Motor class implements LPC1114 H-bridge DC motor driver output services. /// public class Motor { /// /// The motor speed minimum value is -1.0 (full reverse). /// public const double MOTOR_MIN_SPEED = -1.0F; /// /// The motor speed stop value is 0.0. /// public const double MOTOR_STOP = 1.0F; /// /// The motor speed maximum value is 1.0 (full forward). /// public const double MOTOR_MAX_SPEED = 1.0F; private PWM pwmpin; private GPIO dirpin; /// /// LPC1114 H-bridge DC motor driver output object constructor. /// /// SPI Agent Firmware transport object. /// LPC1114 PWM output pin number. /// Allowed values are LPC1114_PWM1 through LPC1114_PWM4. /// LPC1114 direction output pin number. /// Allowed values are LPC1114_GPIO0 through LPC1114_GPIO7. /// PWM pulse frequency. /// Allowed values are 50 to 50000 Hz. public Motor(ITransport spiagent, int pwm_pin, int dir_pin, int frequency = 100) { // Validate parameters if (pwm_pin == dir_pin) { throw new ArgumentException("PWM and direction pins cannot be the same"); } // Configure pins pwmpin = new PWM(spiagent, pwm_pin, frequency); dirpin = new GPIO(spiagent, dir_pin, GPIO.MODE.OUTPUT); // Stop motor speed = MOTOR_STOP; } /// /// This write-only property sets this motor speed. /// Allowed values are -1.0 through 1.0 (normalized speed). /// public double speed { set { // Validate parameters if ((value < MOTOR_MIN_SPEED) || (value > MOTOR_MAX_SPEED)) { throw new ArgumentException("Invalid motor speed value"); } if (value < 0) { dirpin.state = false; pwmpin.dutycycle = -100.0F * value; } else { dirpin.state = true; pwmpin.dutycycle = 100.0F * value; } } } } }