From 18e0d79f4fe53fb3b24f6ae24b032db657332ed2 Mon Sep 17 00:00:00 2001 From: Tom Aarts Date: Fri, 4 Sep 2026 19:54:13 -0500 Subject: [PATCH 1/2] mcp4728 example device --- README.md | 1 + assets/runMcp4728.sh | 2 + pom.xml | 2 +- .../com/pi4j/devices/mcp4728/MCP4728App.java | 305 ++++++++++++++++++ .../devices/mcp4728/MCP4728_Declares.java | 69 ++++ .../java/com/pi4j/devices/mcp4728/README.md | 110 +++++++ 6 files changed, 488 insertions(+), 1 deletion(-) create mode 100644 assets/runMcp4728.sh create mode 100644 src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java create mode 100644 src/main/java/com/pi4j/devices/mcp4728/MCP4728_Declares.java create mode 100644 src/main/java/com/pi4j/devices/mcp4728/README.md diff --git a/README.md b/README.md index e0d61aa..323d68b 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ The following table the currently supported devices within this project: | A/D | SPI | | [MCP3008 A/D 10bit converter](src/main/java/com/pi4j/devices/mcp3008/README.md) | A/D | SPI | | [MCP3208 A/D 12bit converter](src/main/java/com/pi4j/devices/mcp3208/README.md) | D/A | I2C | | [MCP4725 12 bit DAC](src/main/java/com/pi4j/devices/mcp4725/README.md) +| D/A | I2C | | [MCP4728 12 bit DAC 4-ch](src/main/java/com/pi4j/devices/mcp4728/README.md) | D/A | SPI | | [MCP4921 12 bit DAC](src/main/java/com/pi4j/devices/mcp4921/README.md) | D/A | SPI | | [MCP4922 12 bit DAC](src/main/java/com/pi4j/devices/mcp4922/README.md) | HAT | | | [Raspberry SenseHat](src/main/java/com/pi4j/examples/hat/raspberry/sensehat/) diff --git a/assets/runMcp4728.sh b/assets/runMcp4728.sh new file mode 100644 index 0000000..20e88ee --- /dev/null +++ b/assets/runMcp4728.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env bash + java -classpath ./*:../classes com.pi4j.devices.mcp4728.MCP4728App $@ diff --git a/pom.xml b/pom.xml index 9319175..b4292f8 100644 --- a/pom.xml +++ b/pom.xml @@ -34,7 +34,7 @@ 2.0.17 4.0.1 - + 1.6.0 diff --git a/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java b/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java new file mode 100644 index 0000000..428d7d2 --- /dev/null +++ b/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java @@ -0,0 +1,305 @@ + + +package com.pi4j.devices.mcp4728; + +import com.pi4j.Pi4J; +import com.pi4j.context.Context; +import com.pi4j.drivers.io.da.mcp472x.Mcp4728Driver; +import com.pi4j.io.gpio.digital.DigitalInput; +import com.pi4j.io.gpio.digital.DigitalInputConfigBuilder; +import com.pi4j.io.gpio.digital.PullResistance; +import com.pi4j.io.i2c.I2C; +import com.pi4j.io.i2c.I2CImplementation; +import com.pi4j.util.Console; + +/** + * Support MCP4728 DAC. + *

+ * Support the single channel functions of the chip. Example: you cannot set + * all four channels vref bit in a single call. Rather this would require + * four separate calls to the driver code. + *

+ *

+ * *The MCP4728 ships with device address 0x60. To set other address the DAC config registers + * * must be updated. The update process requires the LDAC pin be toggled at a specific point + * * in the I2C command as it is clocked into the chip. This GPIO control within the I2C + * * traffic is not possible with Pi4j. To accomplish this would require ordering the chip with + * * the address programmed, or use of an MCU. + * *

+ * * @see MCP4728 + * * + * + */ +public class MCP4728App { + + static void main(String[] args) { + System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "NONE"); + + Context pi4j = Pi4J.newAutoContext(); + + final Console console = new Console(); + console.print("=============================================================="); + console.print("startup MCP4728App "); + console.print("=============================================================="); + + + + int dataPinNum = -1; + int busNum = 1; + int address = MCP4728_Declares._MCP4728_DEFAULT_ADDRESS; + int channel = 0; + boolean doReset = false; + int registerData = 0; + boolean setOutputEEPROM = false; + boolean setOutputFast = false; + double vref = 0; + float eepromVolt = 0; + float fastVolt = 0; + int onlyOne = 0; // numerous parms a mutually exclusive + int gainBit = 0; + int vrefBit = 1; + boolean setVrefBit = false; + boolean setGainBit = false; + boolean updateEEPROM = false; + + String helpString = " parms: -b 0x? hex value bus -a 0x?? hex value address -d RDY GPIO number \n " + + " -r reset chip -ue update EEPROM -rde update DAC and EEPROM \n" + + " -ev eeprom voltage -fv fast voltage \n" + + " -rdf DAC value update fast -vdd decimal reference voltage\n " + + " -ch channel A B C D -sv vref 0 or 1 -sg gain 0 or 1" + + "-rde -ev -fv -rdf -sv -sg mutually exclusive " ; + + for (int i = 0; i < args.length; i++) { + String o = args[i]; + if (o.contentEquals("-b")) { // bus + String a = args[i + 1]; + busNum = Integer.parseInt(a.substring(2), 16); + i++; + } else if (o.contentEquals("-a")) { // device address + String a = args[i + 1]; + i++; + address = Integer.parseInt(a.substring(2), 16); + } else if (o.contentEquals("-d")) { + String a = args[i + 1]; + dataPinNum = Integer.parseInt(a); + i++; + } else if (o.contentEquals("-sv")) { + String a = args[i + 1]; + vrefBit = Integer.parseInt(a); + setVrefBit = true; + if ( (vrefBit <0) || (vrefBit > 1) ){ + console.println("-vref must be in range 0..1"); + System.exit(54); + } + i++; + onlyOne ++; + } else if (o.contentEquals("-sg")) { + String a = args[i + 1]; + gainBit = Integer.parseInt(a); + setGainBit = true; + if ( (gainBit <0) || (gainBit > 1) ){ + console.println("-vref must be in range 0..1"); + System.exit(55); + } + i++; + onlyOne ++; + } else if (o.contentEquals("-ch")) { + String a = args[i + 1]; + i++; + if (a.equalsIgnoreCase("A")) { + channel = 0; + } else if (a.equalsIgnoreCase("B")) { + channel = 1; + } else if (a.equalsIgnoreCase("C")) { + channel = 2; + } else if (a.equalsIgnoreCase("D")) { + channel = 3; + } else { + console.println(" -ch invalid "); + System.exit(53); + } + } else if (o.contentEquals("-vdd")) { // reference voltage + String a = args[i + 1]; + i++; + vref = Float.parseFloat(a); + } else if (o.contentEquals("-r")) { + doReset = true; + } else if (o.contentEquals("-ue")) { + updateEEPROM = true; + } else if (o.contentEquals("-rde")) { + String a = args[i + 1]; + i++; + registerData = Integer.parseInt(a); + setOutputEEPROM = true; + if (registerData < 0 || registerData > 4095) { + console.println("-rde must be in range 0..4095"); + System.exit(36); + } + onlyOne ++; + } else if (o.contentEquals("-rdf")) { + String a = args[i + 1]; + i++; + setOutputFast = true; + registerData = Integer.parseInt(a); + if (registerData < 0 || registerData > 4095) { + console.println("-rdf must be in range 0..4095"); + System.exit(37); + } + onlyOne ++; + } else if (o.contentEquals("-h")) { + console.println(helpString); + System.exit(39); + } else if (o.contentEquals("-ev")) { // eeprom volts + String a = args[i + 1]; + i++; + eepromVolt = Float.parseFloat(a); + onlyOne ++; + } else if (o.contentEquals("-fv")) { // fast volts + String a = args[i + 1]; + i++; + fastVolt = Float.parseFloat(a); + onlyOne ++; + } else { + console.println(" !!! Invalid Parm " + args); + console.println(helpString); + System.exit(42); + } + } + + if ( dataPinNum == -1 ){ + console.println(" Parameter -d, gpio BCM must be set."); + console.println(helpString); + System.exit(54); + } + if (onlyOne > 1 ) { + console.println(" mutually exclusive parms used."); + console.println(helpString); + System.exit(43); + } + + if ( (vref == 0) || (vref < 0) ){ + console.println("-vdd is zero or less than zero"); + System.exit(50); + + } + if ( (eepromVolt > vref) || (eepromVolt < 0) ) { + console.println("-ev greater than -vdd, or less than zero"); + System.exit(51); + + } + + if ( (fastVolt > vref) || (fastVolt < 0) ) { + console.println("-ef greater than -vdd, or less than zero"); + System.exit(52); + + } + + Mcp4728Driver dacChip ; + I2C genCallDevice = null ; + DigitalInput readyPin = createInputGPIO(dataPinNum, pi4j); + + + I2C i2cDev = createI2cDevice("MCP4728", busNum, address, I2CImplementation.DIRECT, pi4j) ; + dacChip = new Mcp4728Driver( i2cDev, readyPin, vref); + + + if (doReset) { + genCallDevice = createI2cDevice("GenCallReset", busNum,0x00, I2CImplementation.SMBUS, pi4j); + dacChip.resetChip(genCallDevice); + } + + console.println(dacChip.materializeDacDescription()); + + if (setGainBit) { + dacChip.setGain(channel,gainBit); + } + + if (setVrefBit) { + dacChip.setVref(channel,vrefBit); + } + + if (setOutputEEPROM) { + try { + dacChip.setDigitalValueDACEEPROM(channel, registerData); + } catch (Exception e) { + console.println("Error occurred setting DAC output via register value failed. \n Exception " + e.getMessage()); + } + } + if (setOutputFast) { + dacChip.setDigitalValueDAC(channel, registerData); + } + + if (eepromVolt > 0) { + try { + dacChip.setVoltage(channel, eepromVolt); + } catch (Exception e) { + console.println("Error occurred setting DAC output via target voltage failed. \n Exception " + e.getMessage()); + } + } + + + if (fastVolt > 0) { + dacChip.materializeDacRegs() ; + dacChip.setVoltage(channel, fastVolt); + dacChip.materializeDacRegs() ; + } + + if (updateEEPROM) { + dacChip.syncDACToEEPROM(); + } + + console.println(dacChip.materializeDacDescription()); + + + if (genCallDevice != null) { + genCallDevice.close(); + } + if (i2cDev != null) { + i2cDev.close(); + } + + + } + + + /** + * + * @param pinNumber GPIO number + * @param pi4j Context + * @return + */ + static DigitalInput createInputGPIO(int pinNumber, Context pi4j){ + DigitalInputConfigBuilder inputConfig1 = DigitalInput.newConfigBuilder(pi4j) + .id("Data_In_" + pinNumber) + .name("Data_In_" + pinNumber) + .bcm(pinNumber) + .pull(PullResistance.PULL_UP); + return pi4j.create(inputConfig1); + } + + /** + * + * @param chipType String Part numer + * @param bus INT + * @param address INT + * @param pi4j Context + * @return + */ + static I2C createI2cDevice( String chipType, int bus, int address, I2CImplementation impType, Context pi4j) { + String id = String.format("0X%02x: ", bus); + String name = String.format("0X%02x: ", address); + var i2cDeviceConfig = I2C.newConfigBuilder(pi4j) + .bus(bus) + .device(address) + .id(chipType + id + " " + name) + .name(name) + .i2cImplementation(impType) + .build(); + + return pi4j.create(i2cDeviceConfig); + + + } + +} + diff --git a/src/main/java/com/pi4j/devices/mcp4728/MCP4728_Declares.java b/src/main/java/com/pi4j/devices/mcp4728/MCP4728_Declares.java new file mode 100644 index 0000000..3a89744 --- /dev/null +++ b/src/main/java/com/pi4j/devices/mcp4728/MCP4728_Declares.java @@ -0,0 +1,69 @@ + + +package com.pi4j.devices.mcp4728; + + + +public class MCP4728_Declares { + public static final int _MCP4728_DEFAULT_ADDRESS = 0x60; + + public static final int _MCP4728_SET_EEPROM_SIZE = 0x06; + public static final int _MCP4728_SET_FAST_SIZE = 0x04; + public static final int _MCP4728_CHIP_READ_SIZE = 0x05; + + // Table 5.1 + public static final byte _MCP4728_WRITE_CMD_FAST = 0b00000000; + public static final byte _MCP4728_WRITE_CMD_MULTI_DAC_EEPROM = 0b01000000; + public static final byte _MCP4728_WRITE_CMD_SNGL_DAC_EEPROM = 0b01011000; + + public static final byte _MCP4728_WRITE_CMD_I2C_ADDR = 0b01100000; + + + public static final byte _MCP4728_WRITE_CMD_SEQ_DAC_EEPROM = 0b01010000; + + public static final byte _MCP4728_WRITE_CMD_VREF_SLCT_DAC = (byte) 0b10000000; + public static final byte _MCP4728_WRITE_CMD_GAIN_SLCT_DAC = (byte) 0b11000000; + public static final byte _MCP4728_WRITE_CMD_PD_BITS_DAC = (byte) 0b10100000; + + + + + + + + public static final byte _MCP4728_PD_MODE_NORMAL = 0b00000000; + public static final byte _MCP4728_PD_MODE_INOPT = 0b00000110; + + public static final byte _MCP4728_DAC_PD0_MODE_MASK = 0b00000010; + public static final byte _MCP4728_DAC_PD1_MODE_MASK = 0b00000100; + + public static final int _MCP4728_EEPROM_PD1_MODE_MASK = 0b10000000; + public static final byte _MCP4728_EEPROM_PD0_MODE_MASK = 0b01000000; + + // Indicate EEPROM write/update status + public static final byte _MCP4728_READ_CMD_RDY_BSY_MSK = (byte) 0b10000000; + public static final byte _MCP4728_READ_CMD_IS_COMPLT = (byte) 0b10000000; + public static final byte _MCP4728_READ_CMD_IS_NOT_COMPLT = (byte) 0b00000000; + + // POR device load EEPROM + public static final byte _MCP4728_GEN_CALL_RESET_CMD = (byte) 0b00000110; + + // POR device PD1 and PD0 set to 0 for normal operation + public static final byte _MCP4728_GEN_CALL_WAKEUP_CMD = (byte) 0b00001001; + + + // Write + // C2=0 C1=1 C0=0 DAC only + // C2=0 C1=1 C0=1 DAC and EEPROM + // byte1 byte2 byte3 byte4 + // address r/w C2 C1 C0 x x PD1 PD0 X D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 X X X X + + // Read DAC + // byte1 byte2 byte3 byte4 + // address r/w RDY/BSY C1 C0 x x PD1 PD0 X D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 X X X X + + // EEPROM + // byte5 byte6 + // X PD1 PD0 X D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 + +} diff --git a/src/main/java/com/pi4j/devices/mcp4728/README.md b/src/main/java/com/pi4j/devices/mcp4728/README.md new file mode 100644 index 0000000..32b04ec --- /dev/null +++ b/src/main/java/com/pi4j/devices/mcp4728/README.md @@ -0,0 +1,110 @@ +### This repository contains device specific support for various devices. + +### This is an example implementation and will need to be adjusted to fit your needs. + +Project by Tom Aarts +========================================================================== + + Adafruit MCP4728 + +Pi 3.3V Vin +Pi Grnd GND +Pi Pin5 SCL +Pi Pin3 SDA +Pi Grnd LDAC +P1 Gpio12 RDY/BSY + Ch B MCP3008 ch6 + Ch D MCP3008 ch1 + + + +1. ./mvnw clean package +2. cd target/distribution +3. sudo ./runMcp4728.sh parms........ + +https://datasheetspdf.com/pdf-file/634126/MicrochipTechnology/MCP4728/1 + +-rde anf -rdf both have max input value 0x0FFF + +-ef and -ev cannot exceed -vdd + + + + Read output votage on channel 1 of MCP3008 +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rde 2047 -vdd 3.3 -ch D + + + All remainig examples read output votage on channel 6 of MCP3008 + +Updates using raw binary value +To Update DAC and EEPROM, set to 50 % of reference voltage Vin of 3.3 volts + +vrefBit 1 by default vout = 1.0v +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rde 2047 -vdd 3.3 -ch B -d 12 + +set vrefBit 0, uses vdd +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 0 -vdd 3.3 -ch B -d 12 + +vrefBit 0 vout = 1.6 v +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rde 2047 -vdd 3.3 -ch B -d 12 + +To Update DAC Fast, set to 50 % of reference voltage +vrefBit 0, vout 1.6v +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rdf 2047 -vdd 3.3 -ch B -d 12 + +set vrefBit 1, uses 2.048 +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 1 -vdd 3.3 -ch B -d 12 + +set vrefBit 1, set gain to 2x +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sg 1 -vdd 3.3 -ch B -d 12 + +To Update DAC Fast, set to 50 % of reference voltage +vrefBit 0, gain 2x vout 3.3v +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rdf 2047 -vdd 3.3 -ch B -d 12 + + +To Update DAC Fast, set to 100 % of reference voltage +vrefBit 0, vout 3.3v +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rdf 4095 -r -vdd 3.3 -ch B -d 12 + +Updates using voltage value + +To Update DAC Fast, set to 1.8v of reference voltage +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -fv 1.8 -vdd 3.3 -ch B -d 12 + +To Update DAC and EEPROM, set to 3.3v +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -ev 3.3 -vdd 3.3 -ch B -d 12 + +To Update DAC Fast, reset chip, set to 3.1 +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -ev 3.1 -r -vdd 3.3 -ch B -d 12 + + + + + +UNIT TEST +Validate dumps registers show bits updated correctly + +To Update vref bit channel 1 +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 0 -vdd 3.3 -ch B -d 12 + +To Update gain bit channel 1 +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sg 1 -vdd 3.3 -ch B -d 12 + + + + +vref 0 = vdd + 1 = 2.048 + +gain 0 = 1 + 1 = 2x + + + +Test program. Loop indefinitely executing the shell command + +./runLoop.sh program.sh args ...... + +Example usage: +./runLoop.sh ./runMcp3008.sh -vref 3.3 -p 0x0? \ No newline at end of file From 0de05a3b5d689f283d95acb4ffd4d5afb04e7fd5 Mon Sep 17 00:00:00 2001 From: Tom Aarts Date: Fri, 4 Sep 2026 19:54:13 -0500 Subject: [PATCH 2/2] mcp4728 example device # Conflicts: # src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java # src/main/java/com/pi4j/devices/mcp4728/README.md --- .../com/pi4j/devices/mcp4728/MCP4728App.java | 173 +++++++----------- .../java/com/pi4j/devices/mcp4728/README.md | 84 ++++++--- 2 files changed, 124 insertions(+), 133 deletions(-) diff --git a/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java b/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java index 428d7d2..34bfdc3 100644 --- a/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java +++ b/src/main/java/com/pi4j/devices/mcp4728/MCP4728App.java @@ -5,35 +5,45 @@ import com.pi4j.Pi4J; import com.pi4j.context.Context; import com.pi4j.drivers.io.da.mcp472x.Mcp4728Driver; -import com.pi4j.io.gpio.digital.DigitalInput; -import com.pi4j.io.gpio.digital.DigitalInputConfigBuilder; -import com.pi4j.io.gpio.digital.PullResistance; import com.pi4j.io.i2c.I2C; import com.pi4j.io.i2c.I2CImplementation; import com.pi4j.util.Console; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Support MCP4728 DAC. *

- * Support the single channel functions of the chip. Example: you cannot set + * Support the single channel at a time functions of the chip. Example: you cannot set * all four channels vref bit in a single call. Rather this would require * four separate calls to the driver code. *

*

- * *The MCP4728 ships with device address 0x60. To set other address the DAC config registers - * * must be updated. The update process requires the LDAC pin be toggled at a specific point - * * in the I2C command as it is clocked into the chip. This GPIO control within the I2C - * * traffic is not possible with Pi4j. To accomplish this would require ordering the chip with - * * the address programmed, or use of an MCU. - * *

- * * @see MCP4728 - * * + * The MCP4728 ships with device address 0x60. To set other address the DAC config registers + * must be updated. The update process requires the LDAC pin be toggled at a specific point + * in the I2C command as it is clocked into the chip. This GPIO control within the I2C + * traffic is not possible with Pi4j. To accomplish this would require ordering the chip with + * the address programmed, or use of an MCU. + *

+ * @see MCP4728 + * + * + * The MCP4728 chip contains an EEPROM. When Powered-on or RESET, the EEPROM contents are used to update + * the DAC volatile registers, restoring the configured output voltages. The program arguments that result + * in the EEPROM being updated that code examples include the statement dacChip.setEepromEnabled(true);. + * After this method all subsequent methods will ensure the EEPROM is updated. To stop this behavior the + * examples call dacChip.setEepromEnabled(false); + * + * The example uses the letters A B C D to specify the channel. This conforms to the chips Datasheet documentation. + * Within the driver method signatures and code the channel is specified with an int. * */ public class MCP4728App { static void main(String[] args) { - System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "NONE"); + System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "INFO"); + Logger logger = LoggerFactory.getLogger(MCP4728App.class); + logger.trace(">>> Enter: init"); Context pi4j = Pi4J.newAutoContext(); @@ -44,31 +54,30 @@ static void main(String[] args) { - int dataPinNum = -1; int busNum = 1; int address = MCP4728_Declares._MCP4728_DEFAULT_ADDRESS; int channel = 0; boolean doReset = false; int registerData = 0; - boolean setOutputEEPROM = false; - boolean setOutputFast = false; - double vref = 0; - float eepromVolt = 0; - float fastVolt = 0; + double vref = 0; + float volts = 0; int onlyOne = 0; // numerous parms a mutually exclusive int gainBit = 0; int vrefBit = 1; boolean setVrefBit = false; boolean setGainBit = false; - boolean updateEEPROM = false; + boolean setOutputDigital = false; + boolean setOutputVotage = false; + boolean persistValues = false; + - String helpString = " parms: -b 0x? hex value bus -a 0x?? hex value address -d RDY GPIO number \n " + - " -r reset chip -ue update EEPROM -rde update DAC and EEPROM \n" + - " -ev eeprom voltage -fv fast voltage \n" + - " -rdf DAC value update fast -vdd decimal reference voltage\n " + - " -ch channel A B C D -sv vref 0 or 1 -sg gain 0 or 1" + - "-rde -ev -fv -rdf -sv -sg mutually exclusive " ; + String helpString = " parms: -b 0x? hex value bus -a 0x?? hex value address \n " + + " -r reset chip -ch channel A B C D -d digital value (0 ... 4095) \n" + + " -v voltage (0 ... vdd) -pu persist values true/false -vdd decimal reference voltage \n" + + " -sv vrefBit 0 or 1 -sg gainBit 0 or 1 \n" + + "-d -v -sv -sg mutually exclusive \n" ; + ; for (int i = 0; i < args.length; i++) { String o = args[i]; if (o.contentEquals("-b")) { // bus @@ -79,17 +88,13 @@ static void main(String[] args) { String a = args[i + 1]; i++; address = Integer.parseInt(a.substring(2), 16); - } else if (o.contentEquals("-d")) { - String a = args[i + 1]; - dataPinNum = Integer.parseInt(a); - i++; } else if (o.contentEquals("-sv")) { String a = args[i + 1]; vrefBit = Integer.parseInt(a); setVrefBit = true; - if ( (vrefBit <0) || (vrefBit > 1) ){ - console.println("-vref must be in range 0..1"); - System.exit(54); + if ( (gainBit <0) || (gainBit > 1) ){ + console.println("vrefBit must be in range 0..1"); + System.exit(55); } i++; onlyOne ++; @@ -98,7 +103,7 @@ static void main(String[] args) { gainBit = Integer.parseInt(a); setGainBit = true; if ( (gainBit <0) || (gainBit > 1) ){ - console.println("-vref must be in range 0..1"); + console.println("gainBit must be in range 0..1"); System.exit(55); } i++; @@ -124,53 +129,36 @@ static void main(String[] args) { vref = Float.parseFloat(a); } else if (o.contentEquals("-r")) { doReset = true; - } else if (o.contentEquals("-ue")) { - updateEEPROM = true; - } else if (o.contentEquals("-rde")) { + }else if (o.contentEquals("-pv")) { String a = args[i + 1]; + persistValues = Boolean.parseBoolean(a); i++; - registerData = Integer.parseInt(a); - setOutputEEPROM = true; - if (registerData < 0 || registerData > 4095) { - console.println("-rde must be in range 0..4095"); - System.exit(36); - } - onlyOne ++; - } else if (o.contentEquals("-rdf")) { + } else if (o.contentEquals("-d")) { String a = args[i + 1]; i++; - setOutputFast = true; registerData = Integer.parseInt(a); + setOutputDigital = true; if (registerData < 0 || registerData > 4095) { - console.println("-rdf must be in range 0..4095"); - System.exit(37); + console.println("-rde must be in range 0..4095"); + System.exit(36); } onlyOne ++; - } else if (o.contentEquals("-h")) { + } else if (o.contentEquals("-h")) { console.println(helpString); System.exit(39); - } else if (o.contentEquals("-ev")) { // eeprom volts + } else if (o.contentEquals("-v")) { // eeprom volts String a = args[i + 1]; i++; - eepromVolt = Float.parseFloat(a); - onlyOne ++; - } else if (o.contentEquals("-fv")) { // fast volts - String a = args[i + 1]; - i++; - fastVolt = Float.parseFloat(a); + setOutputVotage = true; + volts = Float.parseFloat(a); onlyOne ++; } else { - console.println(" !!! Invalid Parm " + args); + console.println(" !!! Invalid Parm " + o); console.println(helpString); System.exit(42); } } - if ( dataPinNum == -1 ){ - console.println(" Parameter -d, gpio BCM must be set."); - console.println(helpString); - System.exit(54); - } if (onlyOne > 1 ) { console.println(" mutually exclusive parms used."); console.println(helpString); @@ -182,13 +170,13 @@ static void main(String[] args) { System.exit(50); } - if ( (eepromVolt > vref) || (eepromVolt < 0) ) { - console.println("-ev greater than -vdd, or less than zero"); + if ( (volts > vref) || (volts < 0) ) { + console.println("-v greater than -vdd, or less than zero"); System.exit(51); } - if ( (fastVolt > vref) || (fastVolt < 0) ) { + if ( (volts > vref) || (volts < 0) ) { console.println("-ef greater than -vdd, or less than zero"); System.exit(52); @@ -196,11 +184,10 @@ static void main(String[] args) { Mcp4728Driver dacChip ; I2C genCallDevice = null ; - DigitalInput readyPin = createInputGPIO(dataPinNum, pi4j); - + I2C i2cDev = createI2cDevice("MCP4728", busNum, address, I2CImplementation.DIRECT, pi4j) ; - dacChip = new Mcp4728Driver( i2cDev, readyPin, vref); + dacChip = new Mcp4728Driver( i2cDev, vref); if (doReset) { @@ -208,7 +195,9 @@ static void main(String[] args) { dacChip.resetChip(genCallDevice); } - console.println(dacChip.materializeDacDescription()); + logger.info("\nBefore state : \n" + dacChip); + + dacChip.setEepromEnabled(persistValues); if (setGainBit) { dacChip.setGain(channel,gainBit); @@ -218,37 +207,17 @@ static void main(String[] args) { dacChip.setVref(channel,vrefBit); } - if (setOutputEEPROM) { - try { - dacChip.setDigitalValueDACEEPROM(channel, registerData); - } catch (Exception e) { - console.println("Error occurred setting DAC output via register value failed. \n Exception " + e.getMessage()); - } - } - if (setOutputFast) { - dacChip.setDigitalValueDAC(channel, registerData); + if (setOutputDigital) { + dacChip.setDigitalValue(channel, registerData); } - if (eepromVolt > 0) { - try { - dacChip.setVoltage(channel, eepromVolt); - } catch (Exception e) { - console.println("Error occurred setting DAC output via target voltage failed. \n Exception " + e.getMessage()); - } + if (setOutputVotage) { + dacChip.setVoltage(channel, volts); } - if (fastVolt > 0) { - dacChip.materializeDacRegs() ; - dacChip.setVoltage(channel, fastVolt); - dacChip.materializeDacRegs() ; - } - - if (updateEEPROM) { - dacChip.syncDACToEEPROM(); - } - console.println(dacChip.materializeDacDescription()); + logger.info("\nCompletion state : \n" + dacChip); if (genCallDevice != null) { @@ -262,20 +231,6 @@ static void main(String[] args) { } - /** - * - * @param pinNumber GPIO number - * @param pi4j Context - * @return - */ - static DigitalInput createInputGPIO(int pinNumber, Context pi4j){ - DigitalInputConfigBuilder inputConfig1 = DigitalInput.newConfigBuilder(pi4j) - .id("Data_In_" + pinNumber) - .name("Data_In_" + pinNumber) - .bcm(pinNumber) - .pull(PullResistance.PULL_UP); - return pi4j.create(inputConfig1); - } /** * @@ -283,7 +238,7 @@ static DigitalInput createInputGPIO(int pinNumber, Context pi4j){ * @param bus INT * @param address INT * @param pi4j Context - * @return + * @return I2C device */ static I2C createI2cDevice( String chipType, int bus, int address, I2CImplementation impType, Context pi4j) { String id = String.format("0X%02x: ", bus); diff --git a/src/main/java/com/pi4j/devices/mcp4728/README.md b/src/main/java/com/pi4j/devices/mcp4728/README.md index 32b04ec..7222386 100644 --- a/src/main/java/com/pi4j/devices/mcp4728/README.md +++ b/src/main/java/com/pi4j/devices/mcp4728/README.md @@ -12,7 +12,6 @@ Pi Grnd GND Pi Pin5 SCL Pi Pin3 SDA Pi Grnd LDAC -P1 Gpio12 RDY/BSY Ch B MCP3008 ch6 Ch D MCP3008 ch1 @@ -22,6 +21,27 @@ P1 Gpio12 RDY/BSY 2. cd target/distribution 3. sudo ./runMcp4728.sh parms........ +-b 0x? hex value bus +-a 0x?? hex value address +-vdd float reference voltage +-pv true/false. Persist values, default false. +-r reset chip +All following parms effect channel -ch +-ch channel A B C D +-d digital input 0 - 4095 +-v voltage 0 - vdd +-sv vref 0 or 1 +-sg gain 0 or 1" + + +Note -v -d -sv -sg mutually exclusive + +String helpString = " parms: -b 0x? hex value bus -a 0x?? hex value address \n " + +" -r reset chip -ch channel A B C D -d digital value (0 ... 4095) \n" + +" -v voltage (0 ... vdd) -pv persist values true/false -vdd decimal reference voltage \n" + +" -sv vrefBit 0 or 1 -sg gainBit 0 or 1 \n" + +"-d -v -sv -sg mutually exclusive \n" ; + + https://datasheetspdf.com/pdf-file/634126/MicrochipTechnology/MCP4728/1 -rde anf -rdf both have max input value 0x0FFF @@ -36,47 +56,61 @@ sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rde 2047 -vdd 3.3 -ch D All remainig examples read output votage on channel 6 of MCP3008 + +Assume starting with channel B vrefBit 1 use 2.048V, gainBit 0 1x Updates using raw binary value To Update DAC and EEPROM, set to 50 % of reference voltage Vin of 3.3 volts vrefBit 1 by default vout = 1.0v -sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rde 2047 -vdd 3.3 -ch B -d 12 +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -d 2047 -vdd 3.3 -ch B + +vrefBit 1 by default vout = 1.0v persist values +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -d 2047 -vdd 3.3 -ch B -pv true + set vrefBit 0, uses vdd -sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 0 -vdd 3.3 -ch B -d 12 +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 0 -vdd 3.3 -ch B -pv true -vrefBit 0 vout = 1.6 v -sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rde 2047 -vdd 3.3 -ch B -d 12 +vrefBit 0 persisted previous test vout = 1.6 v +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -d 2047 -vdd 3.3 -ch B -To Update DAC Fast, set to 50 % of reference voltage -vrefBit 0, vout 1.6v -sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rdf 2047 -vdd 3.3 -ch B -d 12 set vrefBit 1, uses 2.048 -sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 1 -vdd 3.3 -ch B -d 12 +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 1 -vdd 3.3 -ch B -pv true -set vrefBit 1, set gain to 2x -sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sg 1 -vdd 3.3 -ch B -d 12 +set gainBit 1, set gain to 2x +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sg 1 -vdd 3.3 -ch B -pv true -To Update DAC Fast, set to 50 % of reference voltage -vrefBit 0, gain 2x vout 3.3v -sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rdf 2047 -vdd 3.3 -ch B -d 12 +To Update DAC Fast, set to 50 % of reference voltage with 2x gain +50% 2.048 = 1.0v 2x 1.0 = 2.0v +vrefBit 0, gain 2x vout 2.0v +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -d 2047 -vdd 3.3 -ch B +set vrefBit 0, uses vdd +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 0 -vdd 3.3 -ch B -pv true + To Update DAC Fast, set to 100 % of reference voltage -vrefBit 0, vout 3.3v -sudo ./runMcp4728.sh -b 0x01 -a 0x60 -rdf 4095 -r -vdd 3.3 -ch B -d 12 +vrefBit 0, vout 3.2v 2x gain not used when vrefBit 0 (use vdd) +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -d 4095 -r -vdd 3.3 -ch B Updates using voltage value -To Update DAC Fast, set to 1.8v of reference voltage -sudo ./runMcp4728.sh -b 0x01 -a 0x60 -fv 1.8 -vdd 3.3 -ch B -d 12 +To Update DAC Fast, set to 1.8v vout 1.8v +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -v 1.8 -vdd 3.3 -ch B To Update DAC and EEPROM, set to 3.3v -sudo ./runMcp4728.sh -b 0x01 -a 0x60 -ev 3.3 -vdd 3.3 -ch B -d 12 +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -v 3.3 -vdd 3.3 -ch B -pv true + +To set vrefBit 1 +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 1 -vdd 3.3 -ch B -pv true + +To Update DAC and EEPROM, set to 3.3v ???? +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -v 3.3 -vdd 3.3 -ch B -pv true + To Update DAC Fast, reset chip, set to 3.1 -sudo ./runMcp4728.sh -b 0x01 -a 0x60 -ev 3.1 -r -vdd 3.3 -ch B -d 12 +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -v 3.1 -r -vdd 3.3 -ch B @@ -85,11 +119,13 @@ sudo ./runMcp4728.sh -b 0x01 -a 0x60 -ev 3.1 -r -vdd 3.3 -ch B -d 12 UNIT TEST Validate dumps registers show bits updated correctly -To Update vref bit channel 1 -sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 0 -vdd 3.3 -ch B -d 12 +To Update vref bit channel 1 of MCP3008 +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sv 0 -vdd 3.3 -ch D + +To Update gain bit channel 1 of MCP3008 +sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sg 1 -vdd 3.3 -ch D + -To Update gain bit channel 1 -sudo ./runMcp4728.sh -b 0x01 -a 0x60 -sg 1 -vdd 3.3 -ch B -d 12