From 857bc32261f8a05d02ca49cab952c0e7c87e3531 Mon Sep 17 00:00:00 2001 From: Tom Aarts Date: Wed, 16 Sep 2026 12:18:22 -0500 Subject: [PATCH 01/13] new example device SG90. Requires new driver build as I also added the device there. updated mcp472 5 and 8 to log level INFO. Needed so invalid parms details are visible. --- assets/runDHT22.sh | 2 +- assets/runSG90.sh | 4 + pom.xml | 4 +- .../com/pi4j/devices/mcp4725/MCP4725App.java | 2 +- .../com/pi4j/devices/mcp4728/MCP4728App.java | 2 +- src/main/java/com/pi4j/devices/sg90/README.md | 46 +++++++ .../java/com/pi4j/devices/sg90/SG90_App.java | 130 ++++++++++++++++++ 7 files changed, 185 insertions(+), 5 deletions(-) create mode 100644 assets/runSG90.sh create mode 100644 src/main/java/com/pi4j/devices/sg90/README.md create mode 100644 src/main/java/com/pi4j/devices/sg90/SG90_App.java diff --git a/assets/runDHT22.sh b/assets/runDHT22.sh index 3d9b119..a4f08cd 100644 --- a/assets/runDHT22.sh +++ b/assets/runDHT22.sh @@ -1,2 +1,2 @@ #!/usr/bin/env bash - java -classpath ./*:../classes com.pi4j.devices.dht22.DHT22_App $@ + java -classpath ./*:../classes com.pi4j.devices.dht22.DHT22_App $@ \ No newline at end of file diff --git a/assets/runSG90.sh b/assets/runSG90.sh new file mode 100644 index 0000000..b27f87a --- /dev/null +++ b/assets/runSG90.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + + + java -classpath ./*:../classes com.pi4j.devices.sg90.SG90_App $@ diff --git a/pom.xml b/pom.xml index b4292f8..6e9ad4d 100644 --- a/pom.xml +++ b/pom.xml @@ -33,8 +33,8 @@ 2.0.17 - 4.0.1 - + + 5.0.0-SNAPSHOT 1.6.0 diff --git a/src/main/java/com/pi4j/devices/mcp4725/MCP4725App.java b/src/main/java/com/pi4j/devices/mcp4725/MCP4725App.java index 59a2a94..682aade 100644 --- a/src/main/java/com/pi4j/devices/mcp4725/MCP4725App.java +++ b/src/main/java/com/pi4j/devices/mcp4725/MCP4725App.java @@ -15,7 +15,7 @@ public class MCP4725App { static void main(String[] args) { - System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "OFF"); + System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "INFO"); Logger logger = LoggerFactory.getLogger(MCP4725App.class); logger.trace(">>> Enter: init"); diff --git a/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java b/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java index dc97257..6644a85 100644 --- a/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java +++ b/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java @@ -41,7 +41,7 @@ public class MCP4728App { static void main(String[] args) { - System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "OFF"); + System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "iNFO"); Logger logger = LoggerFactory.getLogger(MCP4728App.class); logger.trace(">>> Enter: init"); diff --git a/src/main/java/com/pi4j/devices/sg90/README.md b/src/main/java/com/pi4j/devices/sg90/README.md new file mode 100644 index 0000000..4e713cd --- /dev/null +++ b/src/main/java/com/pi4j/devices/sg90/README.md @@ -0,0 +1,46 @@ +# SG90 servo motor + +https://www.scribd.com/document/420327552/Servo +This device does not have a customary DataSheet + + + The SG90 defines a specific PWM interface and exactly how the PWN signal + controls the servo + + https://www.friendlywire.com/projects/ne555-servo-safe/SG90-datasheet.pdf + + SG90 Duty Cycle Reference TableAssuming a standard 50Hz frequency (20ms total wave period), + here is how the pulse width and duty cycle map to standard angles for the SG90 Servo Motor Guide: + | Angle (Degrees) | Pulse Width (Us) | Duty Cycle (%) | + |-----------------------------------------------------------------------| + | 0 | 0.5 ms | 2.5 % | + | 45 | 1.0 ms | 5.0 % | + | 90 | 1.5 ms | 7.5 % | + |-----------------------------------------------------------------------| + + + + + SG90 Pi +Grey/Brown Ground +Red 5V +Yellow GPIO18 + + + +1. ./mvnw clean package +2. cd target/distribution +3. ./runSG90.sh args + +-h channel (default 2) set the channel, depending on config.txt 1 2 3 4 +-d degree (default 90) + + +Set ouput shaft at 120 degree + +./runSG90.sh -d 120 + + + +If your configuration uses a channel other than 2 +./runSG90.sh -c 1 -d 120 diff --git a/src/main/java/com/pi4j/devices/sg90/SG90_App.java b/src/main/java/com/pi4j/devices/sg90/SG90_App.java new file mode 100644 index 0000000..d01f3ab --- /dev/null +++ b/src/main/java/com/pi4j/devices/sg90/SG90_App.java @@ -0,0 +1,130 @@ +/* + * /* + * * + * + */ + +package com.pi4j.devices.sg90; + +import com.pi4j.boardinfo.util.PwmChipUtil; +import com.pi4j.drivers.motor.sg90.SG90Driver; +import com.pi4j.io.pwm.Pwm; +import com.pi4j.Pi4J; +import com.pi4j.context.Context; +import com.pi4j.io.pwm.PwmConfig; +import com.pi4j.io.pwm.PwmConfigBuilder; +import com.pi4j.io.pwm.PwmType; +import com.pi4j.util.Console; +import com.pi4j.util.Delay; + + +public class SG90_App { + private static Pwm pwm ; + private static double degree = 90; + private static Integer channel = 2 ; + private static Console console ; + private static SG90Driver sg90 ; + private static final Delay delay = new Delay(); + private static java.util.Scanner scanner; + + public SG90_App() { + super(); + + } + + + /** + *

main.

+ * + * @param args an array of {@link java.lang.String} objects. + * @throws java.lang.Exception if any. + */ + public static void main(String[] args) throws Exception { + System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "INFO"); + + scanner = new java.util.Scanner(System.in); + + console = new Console(); + Context pi4j = Pi4J.newAutoContext(); + console.title("<-- The Pi4J V5 Project Extension -->", "SG90_App"); + String helpString = " Parms: -d Degree -c channel -h HELP"; + + + for (int i = 0; i < args.length; i++) { + String o = args[i]; + if (o.contentEquals("-d")) { + String a = args[i + 1]; + degree = Double.parseDouble(a.substring(0)); + if((degree < 0) || (degree > 180)){ + console.println("-d degree must be in range 0..180"); + System.exit(40); + } + i++; + } else if (o.contentEquals("-c")) { + String a = args[i + 1]; + channel = Integer.parseInt(a.substring(0)); + i++; + }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(42); + } + } + + pwm = createPwm(1, channel, pi4j); + + sg90 = new SG90Driver(pwm); + + sg90.setServoAngle(degree); + + waitChange( 10l); + + pwm.close(); + + } + + static void waitChange(long c){ + while(true){ + delay.setMillis(c).materialize(); + console.println("Enter q - quit, or degree value "); + if (scanner.hasNextInt() ) { + int nextDegree = scanner.nextInt(); + if((nextDegree < 0) || (nextDegree > 180)){ + console.println("-d degree must be in range 0..180"); + }else { + sg90.setServoAngle(nextDegree); + } + } else{ + break; + } + } + } + + static double degreeToDutyCycle(Double degree){ + return (degree/180 * 10 ) + 2.5; + } + + static Pwm createPwm(int servoNumber, Integer channel, Context pi4j) { + + final PwmConfig config = PwmConfigBuilder.newInstance (pi4j) + .id ("sg90Number" + servoNumber) + .name ("SG90 number " + servoNumber) + .channel(3) // this.address) //or 1 LED on gpio13 the second channel + .pwmType(PwmType.HARDWARE) + .initial(0) + .channel(channel) + .chip(PwmChipUtil.getPWMChip()) + .frequency(50) + .shutdown (0) + .build (); + + return pi4j.create (config); + } + +} From b2f8cb168df40483fd1b1bda2b7dfc42b7b34364 Mon Sep 17 00:00:00 2001 From: Tom Aarts Date: Wed, 16 Sep 2026 12:18:22 -0500 Subject: [PATCH 02/13] new example device SG90. Requires new driver build as I also added the device there. updated mcp472 5 and 8 to log level INFO. Needed so invalid parms details are visible. # Conflicts: # src/main/java/com/pi4j/devices/sg90/README.md # src/main/java/com/pi4j/devices/sg90/SG90_App.java --- src/main/java/com/pi4j/devices/sg90/README.md | 2 +- src/main/java/com/pi4j/devices/sg90/SG90_App.java | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/pi4j/devices/sg90/README.md b/src/main/java/com/pi4j/devices/sg90/README.md index 4e713cd..327252a 100644 --- a/src/main/java/com/pi4j/devices/sg90/README.md +++ b/src/main/java/com/pi4j/devices/sg90/README.md @@ -24,7 +24,7 @@ This device does not have a customary DataSheet SG90 Pi Grey/Brown Ground Red 5V -Yellow GPIO18 +Yellow GPIO18 config.sys contains dtoverlay=pwm-2chan diff --git a/src/main/java/com/pi4j/devices/sg90/SG90_App.java b/src/main/java/com/pi4j/devices/sg90/SG90_App.java index d01f3ab..6dbd4b7 100644 --- a/src/main/java/com/pi4j/devices/sg90/SG90_App.java +++ b/src/main/java/com/pi4j/devices/sg90/SG90_App.java @@ -17,7 +17,11 @@ import com.pi4j.util.Console; import com.pi4j.util.Delay; - +/** + * SG90 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 SG90_App { private static Pwm pwm ; private static double degree = 90; @@ -106,9 +110,6 @@ static void waitChange(long c){ } } - static double degreeToDutyCycle(Double degree){ - return (degree/180 * 10 ) + 2.5; - } static Pwm createPwm(int servoNumber, Integer channel, Context pi4j) { From eecddef06b728409045027d2f64074a375804ace Mon Sep 17 00:00:00 2001 From: Tom Aarts Date: Wed, 16 Sep 2026 12:18:22 -0500 Subject: [PATCH 03/13] new example device SG90. Requires new driver build as I also added the device there. updated mcp472 5 and 8 to log level INFO. Needed so invalid parms details are visible. --- src/main/java/com/pi4j/devices/sg90/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/pi4j/devices/sg90/README.md b/src/main/java/com/pi4j/devices/sg90/README.md index 327252a..7858948 100644 --- a/src/main/java/com/pi4j/devices/sg90/README.md +++ b/src/main/java/com/pi4j/devices/sg90/README.md @@ -13,9 +13,9 @@ This device does not have a customary DataSheet here is how the pulse width and duty cycle map to standard angles for the SG90 Servo Motor Guide: | Angle (Degrees) | Pulse Width (Us) | Duty Cycle (%) | |-----------------------------------------------------------------------| - | 0 | 0.5 ms | 2.5 % | - | 45 | 1.0 ms | 5.0 % | - | 90 | 1.5 ms | 7.5 % | + | 0 | 0.5 us | 2.5 % | + | 90 | 1.5 us | 7.5 % | + | 180 | 2.5 us | 12.5 % | |-----------------------------------------------------------------------| From 0d707405938a156d4adad069f5b2cb2165f289c2 Mon Sep 17 00:00:00 2001 From: Tom Aarts Date: Wed, 16 Sep 2026 12:18:22 -0500 Subject: [PATCH 04/13] new example device SG90. Requires new driver build as I also added the device there. updated mcp472 5 and 8 to log level INFO. Needed so invalid parms details are visible. --- src/main/java/com/pi4j/devices/sg90/README.md | 4 ++-- src/main/java/com/pi4j/devices/sg90/SG90_App.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/pi4j/devices/sg90/README.md b/src/main/java/com/pi4j/devices/sg90/README.md index 7858948..539a24c 100644 --- a/src/main/java/com/pi4j/devices/sg90/README.md +++ b/src/main/java/com/pi4j/devices/sg90/README.md @@ -20,7 +20,7 @@ This device does not have a customary DataSheet - + SG90 Pi Grey/Brown Ground Red 5V @@ -37,10 +37,10 @@ Yellow GPIO18 config.sys contains dtoverlay=pwm-2chan Set ouput shaft at 120 degree - ./runSG90.sh -d 120 + If your configuration uses a channel other than 2 ./runSG90.sh -c 1 -d 120 diff --git a/src/main/java/com/pi4j/devices/sg90/SG90_App.java b/src/main/java/com/pi4j/devices/sg90/SG90_App.java index 6dbd4b7..ea73ab3 100644 --- a/src/main/java/com/pi4j/devices/sg90/SG90_App.java +++ b/src/main/java/com/pi4j/devices/sg90/SG90_App.java @@ -64,7 +64,7 @@ public static void main(String[] args) throws Exception { System.exit(40); } i++; - } else if (o.contentEquals("-c")) { + } else if (o.contentEquals("-c")) { String a = args[i + 1]; channel = Integer.parseInt(a.substring(0)); i++; @@ -100,7 +100,7 @@ static void waitChange(long c){ if (scanner.hasNextInt() ) { int nextDegree = scanner.nextInt(); if((nextDegree < 0) || (nextDegree > 180)){ - console.println("-d degree must be in range 0..180"); + console.println("-d degree must be in the range 0..180"); }else { sg90.setServoAngle(nextDegree); } From 16b81f426a02411d8be1c914e71a06036846428b Mon Sep 17 00:00:00 2001 From: Tom Aarts Date: Wed, 16 Sep 2026 12:18:22 -0500 Subject: [PATCH 05/13] remove pom raspberrypi new example device SG90. Requires new driver build as I also added the device there. updated mcp472 5 and 8 to log level INFO. Needed so invalid parms details are visible. --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 6e9ad4d..5af449f 100644 --- a/pom.xml +++ b/pom.xml @@ -119,11 +119,11 @@ - + com.pi4j pi4j-drivers From bfb5496e2cad7d1d3139e8f53bb1db05972ce389 Mon Sep 17 00:00:00 2001 From: Tom Aarts Date: Wed, 16 Sep 2026 12:18:22 -0500 Subject: [PATCH 06/13] remove pom raspberrypi new example device SG90. Requires new driver build as I also added the device there. updated mcp472 5 and 8 to log level INFO. Needed so invalid parms details are visible. --- src/main/java/com/pi4j/devices/sg90/README.md | 3 ++- src/main/java/com/pi4j/devices/sg90/SG90_App.java | 6 +----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/pi4j/devices/sg90/README.md b/src/main/java/com/pi4j/devices/sg90/README.md index 539a24c..5e8458f 100644 --- a/src/main/java/com/pi4j/devices/sg90/README.md +++ b/src/main/java/com/pi4j/devices/sg90/README.md @@ -33,7 +33,8 @@ Yellow GPIO18 config.sys contains dtoverlay=pwm-2chan 3. ./runSG90.sh args -h channel (default 2) set the channel, depending on config.txt 1 2 3 4 --d degree (default 90) +-d degree +-q quit Set ouput shaft at 120 degree diff --git a/src/main/java/com/pi4j/devices/sg90/SG90_App.java b/src/main/java/com/pi4j/devices/sg90/SG90_App.java index ea73ab3..c1d5511 100644 --- a/src/main/java/com/pi4j/devices/sg90/SG90_App.java +++ b/src/main/java/com/pi4j/devices/sg90/SG90_App.java @@ -51,7 +51,7 @@ public static void main(String[] args) throws Exception { console = new Console(); Context pi4j = Pi4J.newAutoContext(); console.title("<-- The Pi4J V5 Project Extension -->", "SG90_App"); - String helpString = " Parms: -d Degree -c channel -h HELP"; + String helpString = " Parms: -d Degree -c channel -q quit -h HELP"; for (int i = 0; i < args.length; i++) { @@ -85,8 +85,6 @@ public static void main(String[] args) throws Exception { sg90 = new SG90Driver(pwm); - sg90.setServoAngle(degree); - waitChange( 10l); pwm.close(); @@ -118,11 +116,9 @@ static Pwm createPwm(int servoNumber, Integer channel, Context pi4j) { .name ("SG90 number " + servoNumber) .channel(3) // this.address) //or 1 LED on gpio13 the second channel .pwmType(PwmType.HARDWARE) - .initial(0) .channel(channel) .chip(PwmChipUtil.getPWMChip()) .frequency(50) - .shutdown (0) .build (); return pi4j.create (config); From 53fc720434f0a415655cb1b546e2727ded828de9 Mon Sep 17 00:00:00 2001 From: Tom Aarts Date: Wed, 16 Sep 2026 12:18:22 -0500 Subject: [PATCH 07/13] POM update. User text change remove pom raspberrypi new example device SG90. Requires new driver build as I also added the device there. updated mcp472 5 and 8 to log level INFO. Needed so invalid parms details are visible. --- pom.xml | 83 +++++++++++-------- .../java/com/pi4j/devices/sg90/SG90_App.java | 2 +- 2 files changed, 48 insertions(+), 37 deletions(-) diff --git a/pom.xml b/pom.xml index 5af449f..0fadc9e 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 25 ${java.version} ${java.version} - 3.2.0 + 3.2.0 3.3.1 5.1.9 3.3.2 @@ -33,9 +33,9 @@ 2.0.17 - - 5.0.0-SNAPSHOT + 5.0.0-SNAPSHOT + 2.0.0-SNAPSHOT 1.6.0 3.13.0 @@ -60,6 +60,17 @@ Sonatype OSS Maven2 Repository https://mvnrepository.com/artifact/org.apache.felix/maven-bundle-plugin + + sonatype-snapshots + Maven Central Snapshots + https://central.sonatype.com/repository/maven-snapshots + + false + + + true + + sonatype-oss-staging Sonatype Open Source Maven Repository @@ -84,27 +95,27 @@ pi4j-plugin-gpiod ${pi4j.version} - + - net.java.dev.jna - jna - 5.12.1 - + net.java.dev.jna + jna + 5.12.1 + + + org.slf4j + slf4j-api + ${slf4j.version} + - org.slf4j - slf4j-api - ${slf4j.version} - - - org.slf4j - slf4j-simple - ${slf4j.version} - - + org.slf4j + slf4j-simple + ${slf4j.version} + + com.pi4j pi4j-core @@ -127,7 +138,7 @@ com.pi4j pi4j-drivers - 1.1.1-SNAPSHOT + ${pi4j-driver.version} org.jetbrains @@ -190,19 +201,19 @@ - + org.apache.maven.plugins maven-source-plugin - ${maven-source-plugin.version} - - - attach-sources - - jar - - - - + ${maven-source-plugin.version} + + + attach-sources + + jar + + + + + com.pi4j.devices.mcp23008/com.pi4j.devices.mcp23008.Mcp23008App @@ -373,7 +384,7 @@ maven-antrun-plugin ${maven-antrun-plugin.version} - + copySH install diff --git a/src/main/java/com/pi4j/devices/sg90/SG90_App.java b/src/main/java/com/pi4j/devices/sg90/SG90_App.java index c1d5511..9a26741 100644 --- a/src/main/java/com/pi4j/devices/sg90/SG90_App.java +++ b/src/main/java/com/pi4j/devices/sg90/SG90_App.java @@ -94,7 +94,7 @@ public static void main(String[] args) throws Exception { static void waitChange(long c){ while(true){ delay.setMillis(c).materialize(); - console.println("Enter q - quit, or degree value "); + console.println("Enter degree value or enter q quit"); if (scanner.hasNextInt() ) { int nextDegree = scanner.nextInt(); if((nextDegree < 0) || (nextDegree > 180)){ From adb9208968d466f1e8f2583bc5cb926f9be02d26 Mon Sep 17 00:00:00 2001 From: Tom Aarts Date: Wed, 16 Sep 2026 12:18:22 -0500 Subject: [PATCH 08/13] POM update. User text change remove pom raspberrypi new example device SG90. Requires new driver build as I also added the device there. updated mcp472 5 and 8 to log level INFO. Needed so invalid parms details are visible. # Conflicts: # src/main/java/com/pi4j/devices/sg90/SG90_App.java --- README.md | 1 + src/main/java/com/pi4j/devices/sg90/README.md | 51 ++++++++++++------- .../java/com/pi4j/devices/sg90/SG90_App.java | 48 +++++++++-------- 3 files changed, 61 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index 323d68b..566711e 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ 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 device](src/main/java/com/pi4j/devices/sg90/README.md) ### Notes: diff --git a/src/main/java/com/pi4j/devices/sg90/README.md b/src/main/java/com/pi4j/devices/sg90/README.md index 5e8458f..cd9cffd 100644 --- a/src/main/java/com/pi4j/devices/sg90/README.md +++ b/src/main/java/com/pi4j/devices/sg90/README.md @@ -1,26 +1,26 @@ # SG90 servo motor https://www.scribd.com/document/420327552/Servo -This device does not have a customary DataSheet +https://www.friendlywire.com/projects/ne555-servo-safe/SG90-datasheet.pdf +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 SG90 defines a specific PWM interface and exactly how the PWN signal - controls the servo +The SG90 defines a specific PWM interface and exactly how the PWN signal +controls the servo. There are many different manufacturers of the SG90 servo. +The pulse width required for setting the servo at 0 degrees or 180 degrees 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. - https://www.friendlywire.com/projects/ne555-servo-safe/SG90-datasheet.pdf +If the servo does not rotate to the desired position, Example: to rotate closer to the 0 degree +point reduce the -low argument, to rotate closer to the 180 degree point 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. - SG90 Duty Cycle Reference TableAssuming a standard 50Hz frequency (20ms total wave period), - here is how the pulse width and duty cycle map to standard angles for the SG90 Servo Motor Guide: - | Angle (Degrees) | Pulse Width (Us) | Duty Cycle (%) | - |-----------------------------------------------------------------------| - | 0 | 0.5 us | 2.5 % | - | 90 | 1.5 us | 7.5 % | - | 180 | 2.5 us | 12.5 % | - |-----------------------------------------------------------------------| - - + SG90 Pi Grey/Brown Ground Red 5V @@ -32,16 +32,29 @@ Yellow GPIO18 config.sys contains dtoverlay=pwm-2chan 2. cd target/distribution 3. ./runSG90.sh args --h channel (default 2) set the channel, depending on config.txt 1 2 3 4 --d degree --q quit +-c channel (default 2) set the channel, depending on config.txt 1 2 3 4 +-low float pulse width for 0 degree microseconds +-high float pulse width for 180 degree microseconds +-q quit +-h help +./runSG90.sh begins execution of the application, you then enter the desired servo degree of rotation. +Then continue entering the requested degree value, or any key will exist the program. Set ouput shaft at 120 degree -./runSG90.sh -d 120 +./runSG90.sh + 120 +Driver defaults to 0 degree requires a 1000 micro second pulse, 180 degree requires a 2000 microsecond pulse +If your servo requires different pulse widths +Set low high pulse widths, then set output shaft at 120 degree +./runSG90.sh -low 600 -high 2400 + 120 +My SG90 aligns correctly with these values +./runSG90.sh -low 550 -high 2450 If your configuration uses a channel other than 2 -./runSG90.sh -c 1 -d 120 +./runSG90.sh -c 1 + 120 diff --git a/src/main/java/com/pi4j/devices/sg90/SG90_App.java b/src/main/java/com/pi4j/devices/sg90/SG90_App.java index 9a26741..b3c0e85 100644 --- a/src/main/java/com/pi4j/devices/sg90/SG90_App.java +++ b/src/main/java/com/pi4j/devices/sg90/SG90_App.java @@ -21,15 +21,23 @@ * SG90 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. + * + * See README.md for more information and detail. */ -public class SG90_App { - private static Pwm pwm ; - private static double degree = 90; - private static Integer channel = 2 ; +class SG90_App { + + 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 Integer channel = DEFAULT_CHANNEL_NUMBER ; private static Console console ; private static SG90Driver sg90 ; private static final Delay delay = new Delay(); private static java.util.Scanner scanner; + private static float lowPulse = 1000; + private static float highPulse = 2000; + public SG90_App() { super(); @@ -43,7 +51,7 @@ public SG90_App() { * @param args an array of {@link java.lang.String} objects. * @throws java.lang.Exception if any. */ - public static void main(String[] args) throws Exception { + static void main(String[] args) throws Exception { System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "INFO"); scanner = new java.util.Scanner(System.in); @@ -51,18 +59,18 @@ public static void main(String[] args) throws Exception { console = new Console(); Context pi4j = Pi4J.newAutoContext(); console.title("<-- The Pi4J V5 Project Extension -->", "SG90_App"); - String helpString = " Parms: -d Degree -c channel -q quit -h HELP"; + String helpString = " Parms: -c channel -q quit -low microseconds -high microseconds -h HELP"; for (int i = 0; i < args.length; i++) { String o = args[i]; - if (o.contentEquals("-d")) { + if (o.contentEquals("-low")) { String a = args[i + 1]; - degree = Double.parseDouble(a.substring(0)); - if((degree < 0) || (degree > 180)){ - console.println("-d degree must be in range 0..180"); - System.exit(40); - } + lowPulse = Integer.parseInt(a.substring(0)); + i++; + } else if (o.contentEquals("-high")) { + String a = args[i + 1]; + highPulse = Integer.parseInt(a.substring(0)); i++; } else if (o.contentEquals("-c")) { String a = args[i + 1]; @@ -81,11 +89,11 @@ public static void main(String[] args) throws Exception { } } - pwm = createPwm(1, channel, pi4j); + Pwm pwm = createPwm(SERVO_NUMBER, channel, pi4j); - sg90 = new SG90Driver(pwm); + sg90 = new SG90Driver(pwm, lowPulse, highPulse); - waitChange( 10l); + waitChange( 10L); pwm.close(); @@ -94,11 +102,11 @@ public static void main(String[] args) throws Exception { static void waitChange(long c){ while(true){ delay.setMillis(c).materialize(); - console.println("Enter degree value or enter q quit"); + console.println("Enter degree value or enter any key to quit"); if (scanner.hasNextInt() ) { - int nextDegree = scanner.nextInt(); + float nextDegree = scanner.nextFloat(); if((nextDegree < 0) || (nextDegree > 180)){ - console.println("-d degree must be in the range 0..180"); + console.println(" degree must be in the range 0..180"); }else { sg90.setServoAngle(nextDegree); } @@ -114,11 +122,11 @@ static Pwm createPwm(int servoNumber, Integer channel, Context pi4j) { final PwmConfig config = PwmConfigBuilder.newInstance (pi4j) .id ("sg90Number" + servoNumber) .name ("SG90 number " + servoNumber) - .channel(3) // this.address) //or 1 LED on gpio13 the second channel + .channel(channel) .pwmType(PwmType.HARDWARE) .channel(channel) .chip(PwmChipUtil.getPWMChip()) - .frequency(50) + .frequency(DEFAULT_PWM_FREQUENCY) .build (); return pi4j.create (config); From 4c1950700938fc0d5f190f353c7ee9ae8eeaffde Mon Sep 17 00:00:00 2001 From: Tom Aarts Date: Wed, 16 Sep 2026 12:18:22 -0500 Subject: [PATCH 09/13] Duplicate what is in the merged code. This was out an modified trying to resolve the errors loading the pi4j core 5.0.0-SNAPSHOT POM update. User text change remove pom raspberrypi new example device SG90. Requires new driver build as I also added the device there. updated mcp472 5 and 8 to log level INFO. Needed so invalid parms details are visible. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0fadc9e..9323460 100644 --- a/pom.xml +++ b/pom.xml @@ -471,4 +471,4 @@ - + \ No newline at end of file From 74555f1a287ec8d602ec814d381f0f8bd39b44b6 Mon Sep 17 00:00:00 2001 From: Tom Aarts Date: Wed, 16 Sep 2026 12:18:22 -0500 Subject: [PATCH 10/13] change float to double Duplicate what is in the merged code. This was out an modified trying to resolve the errors loading the pi4j core 5.0.0-SNAPSHOT POM update. User text change remove pom raspberrypi new example device SG90. Requires new driver build as I also added the device there. updated mcp472 5 and 8 to log level INFO. Needed so invalid parms details are visible. --- src/main/java/com/pi4j/devices/sg90/SG90_App.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/pi4j/devices/sg90/SG90_App.java b/src/main/java/com/pi4j/devices/sg90/SG90_App.java index b3c0e85..61ac9f3 100644 --- a/src/main/java/com/pi4j/devices/sg90/SG90_App.java +++ b/src/main/java/com/pi4j/devices/sg90/SG90_App.java @@ -35,8 +35,8 @@ class SG90_App { private static SG90Driver sg90 ; private static final Delay delay = new Delay(); private static java.util.Scanner scanner; - private static float lowPulse = 1000; - private static float highPulse = 2000; + private static Double lowPulse = 1000.0; + private static Double highPulse = 2000.0; public SG90_App() { @@ -66,11 +66,11 @@ static void main(String[] args) throws Exception { String o = args[i]; if (o.contentEquals("-low")) { String a = args[i + 1]; - lowPulse = Integer.parseInt(a.substring(0)); + lowPulse = Double.parseDouble(a.substring(0)); i++; } else if (o.contentEquals("-high")) { String a = args[i + 1]; - highPulse = Integer.parseInt(a.substring(0)); + highPulse = Double.parseDouble(a.substring(0)); i++; } else if (o.contentEquals("-c")) { String a = args[i + 1]; @@ -104,8 +104,8 @@ static void waitChange(long c){ delay.setMillis(c).materialize(); console.println("Enter degree value or enter any key to quit"); if (scanner.hasNextInt() ) { - float nextDegree = scanner.nextFloat(); - if((nextDegree < 0) || (nextDegree > 180)){ + Double nextDegree = scanner.nextDouble(); + if((nextDegree < 0.0) || (nextDegree > 180.0)){ console.println(" degree must be in the range 0..180"); }else { sg90.setServoAngle(nextDegree); From 48955cfc6745a31101ac29792d6ef98a73201506 Mon Sep 17 00:00:00 2001 From: Tom Aarts Date: Wed, 16 Sep 2026 12:18:22 -0500 Subject: [PATCH 11/13] Change Double to double. The Double class parseDouble retuens a double and the Scanner Double methos also retuns a double. change float to double Duplicate what is in the merged code. This was out an modified trying to resolve the errors loading the pi4j core 5.0.0-SNAPSHOT POM update. User text change remove pom raspberrypi new example device SG90. Requires new driver build as I also added the device there. updated mcp472 5 and 8 to log level INFO. Needed so invalid parms details are visible. # Conflicts: # src/main/java/com/pi4j/devices/sg90/SG90_App.java --- src/main/java/com/pi4j/devices/sg90/SG90_App.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/pi4j/devices/sg90/SG90_App.java b/src/main/java/com/pi4j/devices/sg90/SG90_App.java index 61ac9f3..f7a46ac 100644 --- a/src/main/java/com/pi4j/devices/sg90/SG90_App.java +++ b/src/main/java/com/pi4j/devices/sg90/SG90_App.java @@ -30,13 +30,16 @@ class SG90_App { private static final int DEFAULT_CHANNEL_NUMBER = 2; private static final int SERVO_NUMBER = 1; + private static final double LOW_PULSSE = 1000.0; + private static final double HIGH_PULSE = 2000.0; + private static Integer channel = DEFAULT_CHANNEL_NUMBER ; private static Console console ; private static SG90Driver sg90 ; 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; + private static double lowPulse = LOW_PULSSE; + private static double highPulse = HIGH_PULSE; public SG90_App() { @@ -104,7 +107,7 @@ static void waitChange(long c){ delay.setMillis(c).materialize(); console.println("Enter degree value or enter any key to quit"); if (scanner.hasNextInt() ) { - Double nextDegree = scanner.nextDouble(); + double nextDegree = scanner.nextDouble(); if((nextDegree < 0.0) || (nextDegree > 180.0)){ console.println(" degree must be in the range 0..180"); }else { From 9a6f415e262c2de69100a857c70b71060576100f Mon Sep 17 00:00:00 2001 From: Tom Aarts Date: Wed, 16 Sep 2026 12:18:22 -0500 Subject: [PATCH 12/13] update switch statement Change Double to double. The Double class parseDouble retuens a double and the Scanner Double methos also retuns a double. change float to double Duplicate what is in the merged code. This was out an modified trying to resolve the errors loading the pi4j core 5.0.0-SNAPSHOT POM update. User text change remove pom raspberrypi new example device SG90. Requires new driver build as I also added the device there. updated mcp472 5 and 8 to log level INFO. Needed so invalid parms details are visible. --- src/main/java/com/pi4j/devices/sg90/README.md | 2 +- .../java/com/pi4j/devices/sg90/SG90_App.java | 109 +++++++++--------- 2 files changed, 58 insertions(+), 53 deletions(-) diff --git a/src/main/java/com/pi4j/devices/sg90/README.md b/src/main/java/com/pi4j/devices/sg90/README.md index cd9cffd..e037186 100644 --- a/src/main/java/com/pi4j/devices/sg90/README.md +++ b/src/main/java/com/pi4j/devices/sg90/README.md @@ -20,7 +20,7 @@ Meaning if you reduce the -low by 200, you should increase the -high by 200, or - + Connections between the SG90 servo and the Raspberry Pi SG90 Pi Grey/Brown Ground Red 5V diff --git a/src/main/java/com/pi4j/devices/sg90/SG90_App.java b/src/main/java/com/pi4j/devices/sg90/SG90_App.java index f7a46ac..de9cc1e 100644 --- a/src/main/java/com/pi4j/devices/sg90/SG90_App.java +++ b/src/main/java/com/pi4j/devices/sg90/SG90_App.java @@ -6,11 +6,11 @@ package com.pi4j.devices.sg90; +import com.pi4j.Pi4J; import com.pi4j.boardinfo.util.PwmChipUtil; +import com.pi4j.context.Context; import com.pi4j.drivers.motor.sg90.SG90Driver; import com.pi4j.io.pwm.Pwm; -import com.pi4j.Pi4J; -import com.pi4j.context.Context; import com.pi4j.io.pwm.PwmConfig; import com.pi4j.io.pwm.PwmConfigBuilder; import com.pi4j.io.pwm.PwmType; @@ -18,11 +18,11 @@ import com.pi4j.util.Delay; /** - * SG90 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. - * - * See README.md for more information and detail. + * SG90 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. + *

+ * See README.md for more information and detail. */ class SG90_App { @@ -33,9 +33,9 @@ class SG90_App { private static final double LOW_PULSSE = 1000.0; private static final double HIGH_PULSE = 2000.0; - private static Integer channel = DEFAULT_CHANNEL_NUMBER ; - private static Console console ; - private static SG90Driver sg90 ; + private static Integer channel = DEFAULT_CHANNEL_NUMBER; + private static Console console; + private static SG90Driver sg90; private static final Delay delay = new Delay(); private static java.util.Scanner scanner; private static double lowPulse = LOW_PULSSE; @@ -65,74 +65,79 @@ static void main(String[] args) throws Exception { String helpString = " Parms: -c channel -q quit -low microseconds -high microseconds -h HELP"; + String o; 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("-c")) { - String a = args[i + 1]; - channel = Integer.parseInt(a.substring(0)); - i++; - }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(42); + switch (o = args[i]) { + case "-low" -> { + lowPulse = Integer.parseInt(args[i + 1]); + i++; + } + case "-high" -> { + highPulse = Integer.parseInt(args[i + 1]); + i++; + } + case "-c" -> { + channel = Integer.parseInt(args[i + 1]); + i++; + } + case "-q" -> { + console.println("Exit"); + System.exit(40); + } + case "-h" -> { + console.println(helpString); + System.exit(41); + } + default -> { + console.println(" !!! Invalid Parm " + o); + console.println(helpString); + System.exit(42); + } } } + Pwm pwm = createPwm(SERVO_NUMBER, channel, pi4j); sg90 = new SG90Driver(pwm, lowPulse, highPulse); - waitChange( 10L); + waitChange(10L); pwm.close(); } - static void waitChange(long c){ - while(true){ + static void waitChange(long c) { + while (true) { delay.setMillis(c).materialize(); console.println("Enter degree value or enter any key to quit"); - if (scanner.hasNextInt() ) { + if (scanner.hasNextInt()) { double nextDegree = scanner.nextDouble(); - if((nextDegree < 0.0) || (nextDegree > 180.0)){ + if ((nextDegree < 0.0) || (nextDegree > 180.0)) { console.println(" degree must be in the range 0..180"); - }else { + } else { sg90.setServoAngle(nextDegree); } - } else{ + } else { break; } - } + } } static Pwm createPwm(int servoNumber, Integer channel, Context pi4j) { - final PwmConfig config = PwmConfigBuilder.newInstance (pi4j) - .id ("sg90Number" + servoNumber) - .name ("SG90 number " + servoNumber) - .channel(channel) - .pwmType(PwmType.HARDWARE) - .channel(channel) - .chip(PwmChipUtil.getPWMChip()) - .frequency(DEFAULT_PWM_FREQUENCY) - .build (); - - return pi4j.create (config); + final PwmConfig config = PwmConfigBuilder.newInstance(pi4j) + .id("sg90Number" + servoNumber) + .name("SG90 number " + servoNumber) + .channel(channel) + .pwmType(PwmType.HARDWARE) + .channel(channel) + .chip(PwmChipUtil.getPWMChip()) + .frequency(DEFAULT_PWM_FREQUENCY) + .build(); + + return pi4j.create(config); } } From 310bcef2cdf5efd16ed11ecd27c0b03ca0482fa6 Mon Sep 17 00:00:00 2001 From: Tom Aarts Date: Wed, 16 Sep 2026 12:18:22 -0500 Subject: [PATCH 13/13] review cleanup, included file rename update switch statement Change Double to double. The Double class parseDouble retuens a double and the Scanner Double methos also retuns a double. change float to double Duplicate what is in the merged code. This was out an modified trying to resolve the errors loading the pi4j core 5.0.0-SNAPSHOT POM update. User text change remove pom raspberrypi new example device SG90. Requires new driver build as I also added the device there. updated mcp472 5 and 8 to log level INFO. Needed so invalid parms details are visible. # Conflicts: # src/main/java/com/pi4j/devices/sg90/README.md --- assets/runSG90.sh | 4 ---- assets/runSg90.sh | 4 ++++ src/main/java/com/pi4j/devices/sg90/README.md | 20 +++++++++---------- .../sg90/{SG90_App.java => Sg90App.java} | 6 +++--- 4 files changed, 17 insertions(+), 17 deletions(-) delete mode 100644 assets/runSG90.sh create mode 100644 assets/runSg90.sh rename src/main/java/com/pi4j/devices/sg90/{SG90_App.java => Sg90App.java} (98%) diff --git a/assets/runSG90.sh b/assets/runSG90.sh deleted file mode 100644 index b27f87a..0000000 --- a/assets/runSG90.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash - - - java -classpath ./*:../classes com.pi4j.devices.sg90.SG90_App $@ diff --git a/assets/runSg90.sh b/assets/runSg90.sh new file mode 100644 index 0000000..40854e3 --- /dev/null +++ b/assets/runSg90.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + + + java -classpath ./*:../classes com.pi4j.devices.sg90.Sg90App $@ diff --git a/src/main/java/com/pi4j/devices/sg90/README.md b/src/main/java/com/pi4j/devices/sg90/README.md index e037186..21b2208 100644 --- a/src/main/java/com/pi4j/devices/sg90/README.md +++ b/src/main/java/com/pi4j/devices/sg90/README.md @@ -21,7 +21,7 @@ Meaning if you reduce the -low by 200, you should increase the -high by 200, or Connections between the SG90 servo and the Raspberry Pi - SG90 Pi + SG90 Pi Grey/Brown Ground Red 5V Yellow GPIO18 config.sys contains dtoverlay=pwm-2chan @@ -30,31 +30,31 @@ Yellow GPIO18 config.sys contains dtoverlay=pwm-2chan 1. ./mvnw clean package 2. cd target/distribution -3. ./runSG90.sh args +3. ./runSg90.sh args -c channel (default 2) set the channel, depending on config.txt 1 2 3 4 --low float pulse width for 0 degree microseconds --high float pulse width for 180 degree microseconds +-low double pulse width for 0 degree microseconds +-high double pulse width for 180 degree microseconds -q quit -h help -./runSG90.sh begins execution of the application, you then enter the desired servo degree of rotation. +./runSg90.sh begins execution of the application, you then enter the desired servo degree of rotation. Then continue entering the requested degree value, or any key will exist the program. Set ouput shaft at 120 degree -./runSG90.sh +./runSg90.sh 120 Driver defaults to 0 degree requires a 1000 micro second pulse, 180 degree requires a 2000 microsecond pulse If your servo requires different pulse widths Set low high pulse widths, then set output shaft at 120 degree -./runSG90.sh -low 600 -high 2400 +./runSg90.sh -low 600 -high 2400 120 -My SG90 aligns correctly with these values -./runSG90.sh -low 550 -high 2450 +My Sg90 aligns correctly with these values +./runSg90.sh -low 550 -high 2450 If your configuration uses a channel other than 2 -./runSG90.sh -c 1 +./runSg90.sh -c 1 120 diff --git a/src/main/java/com/pi4j/devices/sg90/SG90_App.java b/src/main/java/com/pi4j/devices/sg90/Sg90App.java similarity index 98% rename from src/main/java/com/pi4j/devices/sg90/SG90_App.java rename to src/main/java/com/pi4j/devices/sg90/Sg90App.java index de9cc1e..cee96e2 100644 --- a/src/main/java/com/pi4j/devices/sg90/SG90_App.java +++ b/src/main/java/com/pi4j/devices/sg90/Sg90App.java @@ -24,7 +24,7 @@ *

* See README.md for more information and detail. */ -class SG90_App { +class Sg90App { private static final int DEFAULT_PWM_FREQUENCY = 50; private static final int DEFAULT_CHANNEL_NUMBER = 2; @@ -42,7 +42,7 @@ class SG90_App { private static double highPulse = HIGH_PULSE; - public SG90_App() { + public Sg90App() { super(); } @@ -61,7 +61,7 @@ static void main(String[] args) throws Exception { console = new Console(); Context pi4j = Pi4J.newAutoContext(); - console.title("<-- The Pi4J V5 Project Extension -->", "SG90_App"); + console.title("<-- The Pi4J V5 Project Extension -->", "Sg90App"); String helpString = " Parms: -c channel -q quit -low microseconds -high microseconds -h HELP";