diff --git a/README.md b/README.md index 323d68b..a0aae67 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,8 @@ The following table the currently supported devices within this project: | Sensor | 1-Wire | (1) | [DHT22 Temp/Humidity sensor](src/main/java/com/pi4j/devices/dht22/README.md) | Sensor | | | [HC-SR04 Ultrasonic Sensor](src/main/java/com/pi4j/devices/hcsr04/README.md) | Sensor | I2C | (1) | [MPL3115A2 Temp/Pressure/Altitude device](src/main/java/com/pi4j/devices/mpl3115a2/README.md) +| Servo | PWM | | [SG90 180 degree servo motor device](src/main/java/com/pi4j/devices/sg90/README.md) +| Servo | PWM | | [FS90R 360 degree continuous servo motor device](src/main/java/com/pi4j/devices/fs90r/README.md) ### Notes: diff --git a/assets/runFs90r.sh b/assets/runFs90r.sh new file mode 100644 index 0000000..4189cb4 --- /dev/null +++ b/assets/runFs90r.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + + + + java -classpath ./*:../classes com.pi4j.devices.fs90r.Fs90rApp $@ diff --git a/src/main/java/com/pi4j/devices/fs90r/Fs90rApp.java b/src/main/java/com/pi4j/devices/fs90r/Fs90rApp.java new file mode 100644 index 0000000..97bdc67 --- /dev/null +++ b/src/main/java/com/pi4j/devices/fs90r/Fs90rApp.java @@ -0,0 +1,196 @@ +/* + * /* + * * + * + */ + +package com.pi4j.devices.fs90r; + + +import com.pi4j.drivers.motor.fs90r.Fs90RDriver; +import com.pi4j.io.pwm.Pwm; +import com.pi4j.io.pwm.PwmConfigBuilder; +import com.pi4j.boardinfo.util.PwmChipUtil; +import com.pi4j.Pi4J; +import com.pi4j.context.Context; +import com.pi4j.io.pwm.PwmConfig; +import com.pi4j.io.pwm.PwmType; +import com.pi4j.util.Console; +import com.pi4j.util.Delay; + + /** + * Example implementation for a FS90R servo motor. + * The Fs90R defines a specific PWM interface and exactly how the PWN signal + * controls the servo + * + * https://www.pololu.com/product/2820 + * + * See the README.md file for example usage and explanation. + * + * FS90R servo motor control. The driver will use the PWM device created by + * this app. It is assumed the device is a HardWare PWM. Hardware PWM creates + * a more consistent PWM signal. + */ + public class Fs90rApp { + + private static final int DEFAULT_PWM_FREQUENCY = 50; + private static final int DEFAULT_CHANNEL_NUMBER = 2; + private static final int SERVO_NUMBER = 1; + + + private static double degree = 90.0; + private static Integer channel = DEFAULT_CHANNEL_NUMBER ; + private static Console console ; + private static Fs90RDriver fs90R ; + private static final Delay delay = new Delay(); + private static java .util.Scanner scanner; + private static double lowPulse = 1000.0; + private static double highPulse = 2000.0; + + + public Fs90rApp() { + super(); + + } + + + /** + *

main.

+ * See the README.md file for example usage. + * @param args an array of {@link java.lang.String} objects. + * @throws java.lang.Exception if any. + */ + static void main(String[] args) throws Exception { + System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "INFO"); + + int onlyOne = 0; // numerous parms a mutually exclusive + + scanner = new java.util.Scanner(System.in); + + console = new Console(); + Context pi4j = Pi4J.newAutoContext(); + console.title("<-- The Pi4J V5 Project Extension -->", "Fs90rApp"); + String helpString = " Parms: -c channel -cw (clockwise) S M F -ccw (counter-clockwise) S M F -h HELP \n" + + " -low microseconds -high microseconds -cw -ccw mutually exclusive -d degree \n" + + " degree must be in the range 0..180. 90 stop, 0..89 CW, 91..180 CCW "; + + + for (int i = 0; i < args.length; i++) { + String o = args[i]; + if (o.contentEquals("-low")) { + String a = args[i + 1]; + lowPulse = Double.parseDouble(a.substring(0)); + i++; + } else if (o.contentEquals("-high")) { + String a = args[i + 1]; + highPulse = Double.parseDouble(a.substring(0)); + i++; + } else if (o.contentEquals("-d")) { + String a = args[i + 1]; + degree = Double.parseDouble(a.substring(0)); + if((!Double.isFinite(degree) || degree < 0) || (degree > 180)){ + console.println("-d degree must be in range 0..180"); + System.exit(40); + } + onlyOne++; + i++; + } else if (o.contentEquals("-c")) { + String a = args[i + 1]; + channel = Integer.parseInt(a.substring(0)); + i++; + } else if (o.contentEquals("-cw")) { /* 0-89 */ + String a = args[i + 1]; + onlyOne++; + i++; + if (a.equalsIgnoreCase("S")) { + degree = 75.0; + } else if (a.equalsIgnoreCase("M")) { + degree = 40.0; + } else if (a.equalsIgnoreCase("F")) { + degree = 0.0; + } else { + console.println(" -cw invalid "); + System.exit(41); + } + } else if (o.contentEquals("-ccw")) { /* 191-180 */ + String a = args[i + 1]; + i++; + onlyOne++; + if (a.equalsIgnoreCase("S")) { + degree = 105.0; + } else if (a.equalsIgnoreCase("M")) { + degree = 140.0; + } else if (a.equalsIgnoreCase("F")) { + degree = 180.0; + } else { + console.println(" -ccw invalid "); + System.exit(42); + } + } else if (o.contentEquals("-q")) { + console.println("Exit"); + System.exit(0); + } else if (o.contentEquals("-h")) { + console.println(helpString); + System.exit(0); + }else { + console.println(" !!! Invalid Parm " + o); + console.println(helpString); + System.exit(43); + } + } + + if (onlyOne > 1 ) { + console.println(" mutually exclusive parms used."); + console.println(helpString); + System.exit(44); + } + Pwm pwm = createPwm(SERVO_NUMBER, channel, pi4j); + + fs90R = new Fs90RDriver(pwm, lowPulse, highPulse); + + // if user did not provide a -cw -ccw or -d default sets stop + fs90R.setServoRotation(degree); + + waitChange( 10l); + + pi4j.shutdown(pwm); + + } + + + static Pwm createPwm(int servoNumber, Integer channel, Context pi4j) { + + final PwmConfig config = PwmConfigBuilder.newInstance (pi4j) + .id ("fs90RNumber" + servoNumber) + .name ("fs90R number " + servoNumber) + .pwmType(PwmType.HARDWARE) + .channel(channel) + .chip(PwmChipUtil.getPWMChip()) + .frequency(DEFAULT_PWM_FREQUENCY) + .build (); + + return pi4j.create (config); + } + + static void waitChange(long c){ + while(true){ + delay.setMillis(c).materialize(); + console.println("Enter q - quit, or degree value "); + if (scanner.hasNextInt() ) { + double nextDegree = scanner.nextDouble(); + if((!Double.isFinite(nextDegree) || nextDegree < 0) || (nextDegree > 180)){ + console.println(" degree must be in the range 0..180. 90 stop, 0..89 CW, 91..180 CCW"); + }else { + fs90R.setServoRotation(nextDegree); + } + } else{ + break; + } + } + } + } + + + + + diff --git a/src/main/java/com/pi4j/devices/fs90r/README.md b/src/main/java/com/pi4j/devices/fs90r/README.md new file mode 100644 index 0000000..b266a57 --- /dev/null +++ b/src/main/java/com/pi4j/devices/fs90r/README.md @@ -0,0 +1,74 @@ + + +##Device application to operate a Fs90r stepping servo. This servo can rotate 360 degree continuously. +The PWM signal sent to the servo device set the direction and RPM of rotation. + + + + Driver for a Fs90r servo motor. + The Fs90r defines a specific PWM interface and exactly how the PWN signal + controls the servo + + https://www.pololu.com/product/2820 + + + These devices do not have a customary DataSheet. Most servo devices provide limited specifications + for required pulse width, they just say 1 - 2 millisecond. + + The FS90 R 360 defines a specific PWM interface and exactly how the PWN signal + controls the servo. There are many different manufacturers of the FS90 servo. + The pulse width required for setting the servo at 0 degrees MAX Clockwise (CW) or 180 degrees + MAX CounterClockWise (CCW) varies by manufacturer. The driver by default uses the pulse width timing as + (low)1000 - (high)2000 microseconds. The user of this example application can change these defaults + when first invoking the program. + + If the servo does not rotate to the expected RPM,Example to rotate faster CW reduce the -low + argument, to rotate CCW faster increase the -high argument. The -low -high change should be balanced or 90 degree will not properly align. + Meaning if you reduce the -low by 200, you should increase the -high by 200, or visa-versa. + + + + + https://www.pololu.com/product/2820 + + + +Fs90r Pi +Grey/Brown Ground +Red 5V +Yellow GPIO18 config.sys contains dtoverlay=pwm-2chan + + + +1. ./mvnw clean package +2. cd target/distribution +3. ./runFs90r.sh args + +-h help +-c channel (default 2) set the channel, depending on config.txt 1 2 3 4 +-cw clockwise S M F +-ccw counter-clockwise S M F +-low double pulse width for 0 degree microseconds +-high double pulse width for 180 degree microseconds +-q quit servo will stop + + +Application running, awaiting input of 0-180 degree +./runFs90r.sh + +Application running CCW, then awaiting input of 0-180 degree +./runFs90r.sh 160 + + + +Set output shaft Fast ClockWise, then enter 90 for stop +./runFs90r.sh -cw F + 90 + + +Set output shaft Slow CounterClockWise, then enter 0 for MAX soeed +./runFs90r.sh -ccw S + 0 + +My Fs90r appears faster rotation wih these values for the -low and -high limmits +./runFs90r.sh -low 550 -high 2450