From f210434765c334c669b5a8321190e76ef6870eeb Mon Sep 17 00:00:00 2001 From: Bane Stojkovic Date: Fri, 14 Aug 2026 14:20:38 +0200 Subject: [PATCH] more components --- .../components/displays/WS2812BStick.java | 200 ++++++++++++++++ .../modules/AnalogJoystickKY023.java | 187 +++++++++++++++ .../components/modules/HC05Bluetooth.java | 195 ++++++++++++++++ .../components/modules/L298NMotorDriver.java | 79 ++++--- .../modules/LM2596BuckConverter.java | 204 +++++++++++++++++ .../components/modules/MB102PowerSupply.java | 207 +++++++++++++++++ .../modules/MOSFETSwitchModule.java | 205 +++++++++++++++++ .../modules/MT3608BoostConverter.java | 181 +++++++++++++++ .../modules/NRF24L01Transceiver.java | 201 ++++++++++++++++ .../modules/PCA9685ServoDriver.java | 216 ++++++++++++++++++ .../diylc/components/modules/RFIDRC522.java | 195 ++++++++++++++++ .../modules/RotaryEncoderKY040.java | 188 +++++++++++++++ .../components/modules/TP4056Charger.java | 183 +++++++++++++++ .../components/modules/ULN2003Driver.java | 201 ++++++++++++++++ .../components/sensors/BME280Sensor.java | 174 ++++++++++++++ .../sensors/SoilMoistureSensor.java | 196 ++++++++++++++++ .../components/sensors/TCRT5000Sensor.java | 188 +++++++++++++++ .../components/maker/MakerComponentsTest.java | 16 ++ 18 files changed, 3180 insertions(+), 36 deletions(-) create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/displays/WS2812BStick.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/modules/AnalogJoystickKY023.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/modules/HC05Bluetooth.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/modules/LM2596BuckConverter.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/modules/MB102PowerSupply.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/modules/MOSFETSwitchModule.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/modules/MT3608BoostConverter.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/modules/NRF24L01Transceiver.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/modules/PCA9685ServoDriver.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/modules/RFIDRC522.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/modules/RotaryEncoderKY040.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/modules/TP4056Charger.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/modules/ULN2003Driver.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/sensors/BME280Sensor.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/sensors/SoilMoistureSensor.java create mode 100644 diylc/diylc-library/src/main/java/org/diylc/components/sensors/TCRT5000Sensor.java diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/displays/WS2812BStick.java b/diylc/diylc-library/src/main/java/org/diylc/components/displays/WS2812BStick.java new file mode 100644 index 00000000..22296ab2 --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/displays/WS2812BStick.java @@ -0,0 +1,200 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.displays; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "NeoPixel Stick (8x WS2812B)", category = "Displays & Outputs", + author = "Branislav Stojkovic", description = "8-LED Addressable RGB WS2812B NeoPixel Stick", + instanceNamePrefix = "LED", zOrder = IDIYComponent.COMPONENT, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class WS2812BStick extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color NEO_BLACK = Color.decode("#111111"); + public static Color LED_PACKAGE = Color.decode("#FDFEFE"); + public static Color LED_DIFFUSER = Color.decode("#EAECEE"); + + public static Size BOARD_WIDTH = new Size(53.0d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(10.2d, SizeUnit.mm); + + public WS2812BStick() { + super(); + this.bodyColor = NEO_BLACK; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double spacing = PIN_SPACING.convertToPixels(); + double w = BOARD_WIDTH.convertToPixels(); + + // 8 pins total: + // Left input header (4 pins): 0 = DIN, 1 = +5V, 2 = GND, 3 = GND + // Right output header (4 pins): 4 = DOUT, 5 = +5V, 6 = GND, 7 = GND + double[][] relativeOffsets = new double[][] { + { 0, 0 }, + { 0, spacing }, + { 0, spacing * 2 }, + { 0, spacing * 3 }, + { w - 20, 0 }, + { w - 20, spacing }, + { w - 20, spacing * 2 }, + { w - 20, spacing * 3 } + }; + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + return new RoundRectangle2D.Double(x - 10, y - 10, boardW, boardH, 4, 4); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - 10; + double boardY = y - 10; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // 8x 5050 SMD WS2812B RGB LEDs + double startX = boardX + 45; + double ledPitch = (boardW - 90) / 7.0; + + for (int i = 0; i < 8; i++) { + double lx = startX + i * ledPitch; + double ly = boardY + boardH / 2.0; + + // 5050 White Package + g2d.setColor(LED_PACKAGE); + g2d.fill(new RoundRectangle2D.Double(lx - 16, ly - 16, 32, 32, 3, 3)); + g2d.setColor(Color.LIGHT_GRAY); + g2d.draw(new RoundRectangle2D.Double(lx - 16, ly - 16, 32, 32, 3, 3)); + + // Circular milky phosphor/lens + g2d.setColor(LED_DIFFUSER); + g2d.fill(new Ellipse2D.Double(lx - 11, ly - 11, 22, 22)); + + // Internal tiny IC dot + g2d.setColor(Color.decode("#333333")); + g2d.fill(new Rectangle2D.Double(lx - 3, ly - 3, 6, 6)); + + // Bypass capacitor + if (i < 7) { + g2d.setColor(Color.decode("#8B6508")); + g2d.fill(new Rectangle2D.Double(lx + ledPitch / 2.0 - 4, ly - 14, 8, 4)); + } + } + + // Silk Screen Pin Labels + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + StringUtils.drawCenteredText(g2d, "DI", boardX + 22, y, HorizontalAlignment.LEFT, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "5V", boardX + 22, y + PIN_SPACING.convertToPixels(), HorizontalAlignment.LEFT, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "GND", boardX + 22, y + PIN_SPACING.convertToPixels() * 2, HorizontalAlignment.LEFT, VerticalAlignment.CENTER); + + StringUtils.drawCenteredText(g2d, "DO", boardX + boardW - 22, y, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "5V", boardX + boardW - 22, y + PIN_SPACING.convertToPixels(), HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "GND", boardX + boardW - 22, y + PIN_SPACING.convertToPixels() * 2, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); + } + + g2d.setTransform(oldTx); + + // Draw input and output header pins + drawPins(g2d, 0, controlPoints.length, false, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(NEO_BLACK); + g2d.fill(new RoundRectangle2D.Double(2, 10, width - 4, height - 20, 2, 2)); + Color[] rainbow = new Color[] { Color.RED, Color.YELLOW, Color.GREEN, Color.CYAN, Color.MAGENTA }; + for (int i = 0; i < 5; i++) { + g2d.setColor(rainbow[i]); + g2d.fill(new Ellipse2D.Double(4 + i * 6, height / 2 - 2, 4, 4)); + } + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/modules/AnalogJoystickKY023.java b/diylc/diylc-library/src/main/java/org/diylc/components/modules/AnalogJoystickKY023.java new file mode 100644 index 00000000..d0a2a3e8 --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/modules/AnalogJoystickKY023.java @@ -0,0 +1,187 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.modules; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "Analog Joystick (KY-023)", category = "Modules & Breakouts", + author = "Branislav Stojkovic", description = "KY-023 Dual-Axis PS2 Thumb Joystick Module with Push Switch", + instanceNamePrefix = "JOY", zOrder = IDIYComponent.COMPONENT, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class AnalogJoystickKY023 extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color JOY_PCB = Color.decode("#1B2631"); + public static Color POT_GREEN = Color.decode("#27AE60"); + public static Color THUMB_CAP = Color.decode("#17202A"); + + public static Size BOARD_WIDTH = new Size(34.0d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(26.0d, SizeUnit.mm); + + public AnalogJoystickKY023() { + super(); + this.bodyColor = JOY_PCB; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double spacing = PIN_SPACING.convertToPixels(); + + // 5-pin 0.1" header: GND, +5V, VRx, VRy, SW + double[][] relativeOffsets = new double[5][2]; + for (int i = 0; i < 5; i++) { + relativeOffsets[i][0] = 0; + relativeOffsets[i][1] = i * spacing; + } + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - boardW + 20; + double boardY = y - (boardH - 4 * PIN_SPACING.convertToPixels()) / 2.0; + return new RoundRectangle2D.Double(boardX, boardY, boardW, boardH, 6, 6); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - boardW + 20; + double boardY = y - (boardH - 4 * PIN_SPACING.convertToPixels()) / 2.0; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // 4 Mounting Holes in corners + drawMountingHole(g2d, boardX + 16, boardY + 16, 16); + drawMountingHole(g2d, boardX + 16, boardY + boardH - 16, 16); + drawMountingHole(g2d, boardX + boardW - 40, boardY + 16, 16); + drawMountingHole(g2d, boardX + boardW - 40, boardY + boardH - 16, 16); + + // Metal Gimbal Frame (Center) + double cx = boardX + (boardW - 30) / 2.0; + double cy = boardY + boardH / 2.0; + g2d.setColor(Color.decode("#7F8C8D")); + g2d.fill(new RoundRectangle2D.Double(cx - 50, cy - 50, 100, 100, 8, 8)); + + // Potentiometer cases (X and Y side blocks) + g2d.setColor(POT_GREEN); + g2d.fill(new RoundRectangle2D.Double(cx - 56, cy - 30, 12, 60, 3, 3)); + g2d.fill(new RoundRectangle2D.Double(cx - 30, cy + 44, 60, 12, 3, 3)); + + // Circular Rubber Thumbstick Cap + g2d.setColor(THUMB_CAP); + g2d.fill(new Ellipse2D.Double(cx - 42, cy - 42, 84, 84)); + g2d.setColor(Color.decode("#2C3E50")); + g2d.fill(new Ellipse2D.Double(cx - 30, cy - 30, 60, 60)); + g2d.setColor(Color.decode("#111111")); + g2d.fill(new Ellipse2D.Double(cx - 20, cy - 20, 40, 40)); + + // Silk Screen Pin Labels + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + String[] labels = new String[] { "GND", "+5V", "VRx", "VRy", "SW" }; + double spacing = PIN_SPACING.convertToPixels(); + for (int i = 0; i < 5; i++) { + StringUtils.drawCenteredText(g2d, labels[i], boardX + boardW - 32, y + i * spacing, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); + } + } + + g2d.setTransform(oldTx); + + // Draw 5 header pins + drawPins(g2d, 0, controlPoints.length, false, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(JOY_PCB); + g2d.fill(new RoundRectangle2D.Double(2, 2, width - 4, height - 4, 3, 3)); + g2d.setColor(THUMB_CAP); + g2d.fill(new Ellipse2D.Double(width / 2.0 - 10, height / 2.0 - 10, 20, 20)); + g2d.setColor(Color.BLACK); + g2d.fill(new Ellipse2D.Double(width / 2.0 - 5, height / 2.0 - 5, 10, 10)); + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/modules/HC05Bluetooth.java b/diylc/diylc-library/src/main/java/org/diylc/components/modules/HC05Bluetooth.java new file mode 100644 index 00000000..be6ea20e --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/modules/HC05Bluetooth.java @@ -0,0 +1,195 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.modules; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "Bluetooth Module (HC-05 / HC-06)", category = "Modules & Breakouts", + author = "Branislav Stojkovic", description = "HC-05 / HC-06 Serial Bluetooth SPP Module Breakout", + instanceNamePrefix = "BT", zOrder = IDIYComponent.COMPONENT, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class HC05Bluetooth extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color BT_BLUE = Color.decode("#1B4F72"); + public static Color DAUGHTER_BOARD = Color.decode("#154360"); + + public static Size BOARD_WIDTH = new Size(37.0d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(16.0d, SizeUnit.mm); + + public HC05Bluetooth() { + super(); + this.bodyColor = BT_BLUE; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double spacing = PIN_SPACING.convertToPixels(); + + // 6-pin 0.1" header: STATE, RXD, TXD, GND, VCC, EN + double[][] relativeOffsets = new double[6][2]; + for (int i = 0; i < 6; i++) { + relativeOffsets[i][0] = 0; + relativeOffsets[i][1] = i * spacing; + } + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - boardW + 20; + double boardY = y - (boardH - 5 * PIN_SPACING.convertToPixels()) / 2.0; + return new RoundRectangle2D.Double(boardX, boardY, boardW, boardH, 4, 4); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - boardW + 20; + double boardY = y - (boardH - 5 * PIN_SPACING.convertToPixels()) / 2.0; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // Bluetooth Daughterboard (HC-05 Core Module) + double dbX = boardX + 15; + double dbY = boardY + 12; + double dbW = boardW - 55; + double dbH = boardH - 24; + + g2d.setColor(DAUGHTER_BOARD); + g2d.fill(new RoundRectangle2D.Double(dbX, dbY, dbW, dbH, 3, 3)); + g2d.setColor(Color.decode("#2E86C1")); + g2d.draw(new RoundRectangle2D.Double(dbX, dbY, dbW, dbH, 3, 3)); + + // Metal RF Shield on daughterboard + g2d.setColor(METAL_SHIELD_COLOR); + g2d.fill(new RoundRectangle2D.Double(dbX + 15, dbY + 10, dbW - 40, dbH - 20, 3, 3)); + g2d.setColor(METAL_SHIELD_BORDER); + g2d.draw(new RoundRectangle2D.Double(dbX + 15, dbY + 10, dbW - 40, dbH - 20, 3, 3)); + g2d.setColor(Color.decode("#555555")); + g2d.setFont(SILK_FONT_SMALL); + StringUtils.drawCenteredText(g2d, "HC-05", dbX + 15 + (dbW - 40) / 2.0, dbY + dbH / 2.0, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + + // Gold PCB Antenna on left tip of daughterboard + g2d.setColor(Color.decode("#D4AC0D")); + g2d.fillRect((int)(dbX + 4), (int)(dbY + 8), 8, (int)(dbH - 16)); + + // Tactile Key/EN Push Button (Top Right) + g2d.setColor(Color.LIGHT_GRAY); + g2d.fill(new RoundRectangle2D.Double(boardX + boardW - 35, boardY + 10, 14, 14, 2, 2)); + g2d.setColor(Color.DARK_GRAY); + g2d.fill(new Ellipse2D.Double(boardX + boardW - 32, boardY + 13, 8, 8)); + + // Status LED (Blue, Bottom Right) + g2d.setColor(Color.CYAN); + g2d.fill(new RoundRectangle2D.Double(boardX + boardW - 34, boardY + boardH - 24, 12, 10, 2, 2)); + + // Silk Screen Pin Labels + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + String[] labels = new String[] { "STATE", "RXD", "TXD", "GND", "VCC", "EN" }; + double spacing = PIN_SPACING.convertToPixels(); + for (int i = 0; i < 6; i++) { + StringUtils.drawCenteredText(g2d, labels[i], boardX + boardW - 24, y + i * spacing, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); + } + } + + g2d.setTransform(oldTx); + + // Draw 6 header pins + drawPins(g2d, 0, controlPoints.length, false, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(BT_BLUE); + g2d.fill(new RoundRectangle2D.Double(2, 4, width - 4, height - 8, 3, 3)); + g2d.setColor(METAL_SHIELD_COLOR); + g2d.fillRect(6, height / 2 - 4, 10, 8); + g2d.setColor(Color.CYAN); + g2d.fill(new Ellipse2D.Double(width - 10, height / 2 - 3, 6, 6)); + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/modules/L298NMotorDriver.java b/diylc/diylc-library/src/main/java/org/diylc/components/modules/L298NMotorDriver.java index 82fbd6c4..64d38206 100644 --- a/diylc/diylc-library/src/main/java/org/diylc/components/modules/L298NMotorDriver.java +++ b/diylc/diylc-library/src/main/java/org/diylc/components/modules/L298NMotorDriver.java @@ -16,7 +16,7 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with DIYLC. If not, see . + * along with DIYLC. If not, see . * */ package org.diylc.components.modules; @@ -89,33 +89,30 @@ public class L298NMotorDriver extends AbstractMakerBoard { @Override protected void updateControlPoints() { Point2D firstPoint = controlPoints[0]; - double termSpacing = new Size(5.08d, SizeUnit.mm).convertToPixels(); // ~40px + double termSpacing = new Size(5.08d, SizeUnit.mm).convertToPixels(); // 40px double pinSpacing = PIN_SPACING.convertToPixels(); // 20px + double boardSizePx = BOARD_SIZE.convertToPixels(); + double boardX = -45; - double[][] relativeOffsets = new double[13][2]; - - // Power screw terminal (0..2) at bottom-left - for (int i = 0; i < 3; i++) { - relativeOffsets[i][0] = i * termSpacing; - relativeOffsets[i][1] = 0; - } - // Motor A terminal (3..4) on left edge - double leftX = -40; - double leftY = -120; - relativeOffsets[3] = new double[] {leftX, leftY}; - relativeOffsets[4] = new double[] {leftX, leftY - termSpacing}; - - // Motor B terminal (5..6) on right edge - double rightX = 240; - relativeOffsets[5] = new double[] {rightX, leftY}; - relativeOffsets[6] = new double[] {rightX, leftY - termSpacing}; - - // Logic header (7..12) at bottom-right - double logicX = 120; - for (int i = 0; i < 6; i++) { - relativeOffsets[7 + i][0] = logicX + i * pinSpacing; - relativeOffsets[7 + i][1] = 0; - } + double[][] relativeOffsets = new double[][] { + // Power screw terminal (0..2) at bottom-left: 12V, GND, 5V + { 0, 0 }, + { termSpacing, 0 }, + { termSpacing * 2, 0 }, + // Motor A terminal (3..4) on left edge: OUT1, OUT2 + { boardX + 22.5, -140 }, + { boardX + 22.5, -180 }, + // Motor B terminal (5..6) on right edge: OUT3, OUT4 + { boardX + boardSizePx - 22.5, -140 }, + { boardX + boardSizePx - 22.5, -180 }, + // Logic header (7..12) at bottom-right: ENA, IN1, IN2, IN3, IN4, ENB + { 140, 0 }, + { 140 + pinSpacing, 0 }, + { 140 + pinSpacing * 2, 0 }, + { 140 + pinSpacing * 3, 0 }, + { 140 + pinSpacing * 4, 0 }, + { 140 + pinSpacing * 5, 0 } + }; rotatePoints(firstPoint, relativeOffsets); } @@ -126,8 +123,8 @@ public class L298NMotorDriver extends AbstractMakerBoard { double x = p0.getX(); double y = p0.getY(); double boardSizePx = BOARD_SIZE.convertToPixels(); - double boardX = x - 55; - double boardY = y - boardSizePx + 20; + double boardX = x - 45; + double boardY = y - boardSizePx + 25; return new RoundRectangle2D.Double(boardX, boardY, boardSizePx, boardSizePx, 10, 10); } @@ -148,8 +145,8 @@ public class L298NMotorDriver extends AbstractMakerBoard { } double boardSizePx = BOARD_SIZE.convertToPixels(); - double boardX = x - 55; - double boardY = y - boardSizePx + 20; + double boardX = x - 45; + double boardY = y - boardSizePx + 25; Shape boardShape = getBodyShape(); @@ -192,17 +189,27 @@ public class L298NMotorDriver extends AbstractMakerBoard { // Green screw terminal block bodies g2d.setColor(SCREW_TERMINAL_COLOR); - // Power terminal - g2d.fill(new RoundRectangle2D.Double(x - 15, y - 25, 110, 35, 3, 3)); - // Motor A terminal - g2d.fill(new RoundRectangle2D.Double(x - 55, y - 175, 35, 75, 3, 3)); - // Motor B terminal - g2d.fill(new RoundRectangle2D.Double(x + 225, y - 175, 35, 75, 3, 3)); + // Power terminal (3 pins) + g2d.fill(new RoundRectangle2D.Double(x - 15, y - 25, 120, 35, 3, 3)); + // Motor A terminal (2 pins) + g2d.fill(new RoundRectangle2D.Double(boardX + 5, y - 195, 35, 75, 3, 3)); + // Motor B terminal (2 pins) + g2d.fill(new RoundRectangle2D.Double(boardX + boardSizePx - 40, y - 195, 35, 75, 3, 3)); + + // Logic header black block + g2d.setColor(HEADER_BODY_COLOR); + g2d.fill(new RoundRectangle2D.Double(x + 130, y - 10, 128, 20, 2, 2)); // Silkscreen g2d.setColor(Color.WHITE); g2d.setFont(SILK_FONT); StringUtils.drawCenteredText(g2d, "L298N DRIVER", boardX + boardSizePx / 2.0, boardY + 30, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + + // Terminal Silk labels + g2d.setFont(SILK_FONT_SMALL); + StringUtils.drawCenteredText(g2d, "12V GND 5V", x + 40, y - 32, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "OUT1/2", boardX + 50, y - 160, HorizontalAlignment.LEFT, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "OUT3/4", boardX + boardSizePx - 50, y - 160, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); } g2d.setTransform(oldTx); diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/modules/LM2596BuckConverter.java b/diylc/diylc-library/src/main/java/org/diylc/components/modules/LM2596BuckConverter.java new file mode 100644 index 00000000..516a0a47 --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/modules/LM2596BuckConverter.java @@ -0,0 +1,204 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.modules; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "Buck Converter (LM2596)", category = "Modules & Breakouts", + author = "Branislav Stojkovic", description = "LM2596 Adjustable DC-DC Step-Down Buck Converter Module", + instanceNamePrefix = "MOD", zOrder = IDIYComponent.COMPONENT, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class LM2596BuckConverter extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color BUCK_BLUE = Color.decode("#1F618D"); + public static Color POT_BLUE = Color.decode("#0055AA"); + public static Color COPPER_COIL = Color.decode("#D35400"); + + public static Size BOARD_WIDTH = new Size(43.0d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(21.0d, SizeUnit.mm); + + public LM2596BuckConverter() { + super(); + this.bodyColor = BUCK_BLUE; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double h = BOARD_HEIGHT.convertToPixels(); + double w = BOARD_WIDTH.convertToPixels(); + + // 4 Solder / Screw terminal pads: + // Input (Left): 0 = IN+, 1 = IN- + // Output (Right): 2 = OUT+, 3 = OUT- + double[][] relativeOffsets = new double[][] { + { 0, 0 }, // Pin 0: IN+ + { 0, h - 20 }, // Pin 1: IN- + { w - 20, 0 }, // Pin 2: OUT+ + { w - 20, h - 20 } // Pin 3: OUT- + }; + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + return new RoundRectangle2D.Double(x - 10, y - 10, boardW, boardH, 6, 6); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - 10; + double boardY = y - 10; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // 2 Diagonal Mounting holes + drawMountingHole(g2d, boardX + 45, boardY + 16, 16); + drawMountingHole(g2d, boardX + boardW - 45, boardY + boardH - 16, 16); + + // Input Capacitor (Left) + g2d.setColor(Color.LIGHT_GRAY); + g2d.fill(new Ellipse2D.Double(boardX + 22, boardY + boardH / 2.0 - 18, 36, 36)); + g2d.setColor(Color.DARK_GRAY); + g2d.draw(new Ellipse2D.Double(boardX + 22, boardY + boardH / 2.0 - 18, 36, 36)); + + // Output Capacitor (Right) + g2d.setColor(Color.LIGHT_GRAY); + g2d.fill(new Ellipse2D.Double(boardX + boardW - 58, boardY + boardH / 2.0 - 18, 36, 36)); + g2d.setColor(Color.DARK_GRAY); + g2d.draw(new Ellipse2D.Double(boardX + boardW - 58, boardY + boardH / 2.0 - 18, 36, 36)); + + // LM2596 IC (Center Left) with tab + g2d.setColor(Color.decode("#333333")); + g2d.fill(new RoundRectangle2D.Double(boardX + 70, boardY + 15, 38, 48, 3, 3)); + g2d.setColor(Color.decode("#CCCCCC")); + g2d.fill(new RoundRectangle2D.Double(boardX + 70, boardY + 12, 38, 10, 2, 2)); + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + StringUtils.drawCenteredText(g2d, "LM2596", boardX + 89, boardY + 38, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + + // Toroidal Power Inductor (Center Right) + g2d.setColor(Color.decode("#222222")); + g2d.fill(new Ellipse2D.Double(boardX + 120, boardY + boardH / 2.0 - 24, 48, 48)); + g2d.setColor(COPPER_COIL); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(3)); + g2d.draw(new Ellipse2D.Double(boardX + 124, boardY + boardH / 2.0 - 20, 40, 40)); + + // Blue 3296W Trimmer Potentiometer (Top Center) + g2d.setColor(POT_BLUE); + g2d.fill(new RoundRectangle2D.Double(boardX + 185, boardY + 15, 45, 26, 3, 3)); + // Brass screw head + g2d.setColor(Color.decode("#D4AC0D")); + g2d.fill(new Ellipse2D.Double(boardX + 190, boardY + 22, 12, 12)); + g2d.setColor(Color.BLACK); + g2d.drawLine((int)(boardX + 192), (int)(boardY + 28), (int)(boardX + 200), (int)(boardY + 28)); + + // Silk Screen Text + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + StringUtils.drawCenteredText(g2d, "IN+", boardX + 14, boardY + 10, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "IN-", boardX + 14, boardY + boardH - 10, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "OUT+", boardX + boardW - 14, boardY + 10, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "OUT-", boardX + boardW - 14, boardY + boardH - 10, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + } + + g2d.setTransform(oldTx); + + // Draw connection pads + drawScrewTerminals(g2d, 0, controlPoints.length, 0, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(BUCK_BLUE); + g2d.fill(new RoundRectangle2D.Double(2, 6, width - 4, height - 12, 3, 3)); + g2d.setColor(COPPER_COIL); + g2d.fill(new Ellipse2D.Double(width / 2 - 4, height / 2 - 4, 8, 8)); + g2d.setColor(POT_BLUE); + g2d.fillRect(width - 12, height / 2 - 5, 8, 10); + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/modules/MB102PowerSupply.java b/diylc/diylc-library/src/main/java/org/diylc/components/modules/MB102PowerSupply.java new file mode 100644 index 00000000..cb2f10ad --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/modules/MB102PowerSupply.java @@ -0,0 +1,207 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.modules; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "Breadboard Power Supply (MB102)", category = "Modules & Breakouts", + author = "Branislav Stojkovic", description = "MB102 Dual 3.3V/5V Breadboard Power Supply Module", + instanceNamePrefix = "PWR", zOrder = IDIYComponent.BOARD, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class MB102PowerSupply extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color MB102_PCB = Color.decode("#E8E4D9"); + public static Color JUMPER_YELLOW = Color.decode("#F1C40F"); + public static Color SWITCH_RED = Color.decode("#E74C3C"); + + public static Size BOARD_WIDTH = new Size(32.0d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(54.0d, SizeUnit.mm); + + public MB102PowerSupply() { + super(); + this.bodyColor = MB102_PCB; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double spacing = PIN_SPACING.convertToPixels(); + + // 8 output pins to plug directly into breadboard power rails: + // Top Power Rail (4 pins: 0..3): +, -, +, - + // Bottom Power Rail (4 pins: 4..7): +, -, +, - spaced 18 grid units apart + double railSpan = 18 * spacing; + double[][] relativeOffsets = new double[][] { + { 0, 0 }, + { spacing, 0 }, + { 0, spacing }, + { spacing, spacing }, + { 0, railSpan }, + { spacing, railSpan }, + { 0, railSpan + spacing }, + { spacing, railSpan + spacing } + }; + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - boardW + PIN_SPACING.convertToPixels() + 25; + double boardY = y - 20; + return new RoundRectangle2D.Double(boardX, boardY, boardW, boardH, 8, 8); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - boardW + PIN_SPACING.convertToPixels() + 25; + double boardY = y - 20; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // DC Barrel Jack (Left Edge Center) + g2d.setColor(Color.decode("#111111")); + g2d.fill(new RoundRectangle2D.Double(boardX - 8, boardY + boardH / 2.0 - 25, 45, 50, 4, 4)); + g2d.setColor(Color.decode("#333333")); + g2d.draw(new RoundRectangle2D.Double(boardX - 8, boardY + boardH / 2.0 - 25, 45, 50, 4, 4)); + g2d.setColor(Color.LIGHT_GRAY); + g2d.fill(new Ellipse2D.Double(boardX - 4, boardY + boardH / 2.0 - 10, 20, 20)); + g2d.setColor(Color.BLACK); + g2d.fill(new Ellipse2D.Double(boardX + 1, boardY + boardH / 2.0 - 5, 10, 10)); + + // USB-A Connector (Center) + drawMetalConnector(g2d, boardX + 45, boardY + boardH / 2.0 - 22, 48, 44, "USB"); + + // Push Button Latch Switch (Left-ish) + g2d.setColor(Color.LIGHT_GRAY); + g2d.fill(new RoundRectangle2D.Double(boardX + 48, boardY + 45, 28, 28, 4, 4)); + g2d.setColor(SWITCH_RED); + g2d.fill(new Ellipse2D.Double(boardX + 53, boardY + 50, 18, 18)); + + // Power Green LED + g2d.setColor(Color.decode("#2ECC71")); + g2d.fill(new Ellipse2D.Double(boardX + 85, boardY + 54, 10, 10)); + + // AMS1117 Voltage Regulators (3.3V and 5.0V) + drawChip(g2d, boardX + 110, boardY + 70, 28, 22, "3.3V"); + drawChip(g2d, boardX + 110, boardY + boardH - 92, 28, 22, "5.0V"); + + // Voltage Selection Jumpers (Top & Bottom rail selectors) + g2d.setColor(JUMPER_YELLOW); + g2d.fill(new RoundRectangle2D.Double(boardX + boardW - 75, boardY + 20, 26, 18, 3, 3)); + g2d.fill(new RoundRectangle2D.Double(boardX + boardW - 75, boardY + boardH - 38, 26, 18, 3, 3)); + + // Silk Screen Text + g2d.setColor(Color.DARK_GRAY); + g2d.setFont(SILK_FONT_SMALL); + StringUtils.drawCenteredText(g2d, "MB102", boardX + boardW / 2.0, boardY + boardH - 60, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "3.3V / 5V", boardX + boardW / 2.0, boardY + boardH - 48, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + + // Rail markings (+ / -) + g2d.setColor(Color.RED); + g2d.drawString("+", (int)(x - 12), (int)(y + 8)); + g2d.drawString("+", (int)(x - 12), (int)(y + 18 * PIN_SPACING.convertToPixels() + 8)); + g2d.setColor(Color.BLUE); + g2d.drawString("-", (int)(x + PIN_SPACING.convertToPixels() + 6), (int)(y + 8)); + g2d.drawString("-", (int)(x + PIN_SPACING.convertToPixels() + 6), (int)(y + 18 * PIN_SPACING.convertToPixels() + 8)); + } + + g2d.setTransform(oldTx); + + // Draw header pins connecting to breadboard rails + drawPins(g2d, 0, controlPoints.length, false, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(MB102_PCB); + g2d.fill(new RoundRectangle2D.Double(4, 2, width - 8, height - 4, 3, 3)); + g2d.setColor(SWITCH_RED); + g2d.fill(new Ellipse2D.Double(width / 2.0 - 4, height / 2.0 - 4, 8, 8)); + g2d.setColor(Color.DARK_GRAY); + g2d.draw(new RoundRectangle2D.Double(4, 2, width - 8, height - 4, 3, 3)); + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/modules/MOSFETSwitchModule.java b/diylc/diylc-library/src/main/java/org/diylc/components/modules/MOSFETSwitchModule.java new file mode 100644 index 00000000..2d33223e --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/modules/MOSFETSwitchModule.java @@ -0,0 +1,205 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.modules; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "MOSFET Driver Module (IRF520)", category = "Modules & Breakouts", + author = "Branislav Stojkovic", description = "IRF520 High-Current DC MOSFET Power Switch Driver Module", + instanceNamePrefix = "MOD", zOrder = IDIYComponent.COMPONENT, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class MOSFETSwitchModule extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color MOSFET_RED = Color.decode("#922B21"); + + public static Size BOARD_WIDTH = new Size(33.0d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(24.0d, SizeUnit.mm); + + public MOSFETSwitchModule() { + super(); + this.bodyColor = MOSFET_RED; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double spacing = PIN_SPACING.convertToPixels(); + double w = BOARD_WIDTH.convertToPixels(); + double h = BOARD_HEIGHT.convertToPixels(); + + // 7 pins total: + // Pin 0..2: Control header (SIG, VCC, GND on left) + // Pin 3, 4: VIN, GND (Power in screw terminal, top right) + // Pin 5, 6: V+, V- (Load out screw terminal, bottom right) + double[][] relativeOffsets = new double[][] { + { 0, 0 }, + { 0, spacing }, + { 0, spacing * 2 }, + { w - 30, -spacing * 1.5 }, + { w - 30, -spacing * 0.5 }, + { w - 30, spacing * 1.5 }, + { w - 30, spacing * 2.5 } + }; + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - 15; + double boardY = y - (boardH - 2 * PIN_SPACING.convertToPixels()) / 2.0; + return new RoundRectangle2D.Double(boardX, boardY, boardW, boardH, 6, 6); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - 15; + double boardY = y - (boardH - 2 * PIN_SPACING.convertToPixels()) / 2.0; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // 2 Mounting Holes + drawMountingHole(g2d, boardX + 14, boardY + 14, 14); + drawMountingHole(g2d, boardX + 14, boardY + boardH - 14, 14); + + // TO-220 Power MOSFET (Center) + double mosX = boardX + 50; + double mosY = boardY + boardH / 2.0 - 24; + g2d.setColor(Color.decode("#222222")); + g2d.fill(new RoundRectangle2D.Double(mosX, mosY, 36, 48, 3, 3)); + // Heatsink tab + g2d.setColor(Color.decode("#BDC3C7")); + g2d.fill(new RoundRectangle2D.Double(mosX, mosY - 10, 36, 12, 2, 2)); + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + StringUtils.drawCenteredText(g2d, "IRF520", mosX + 18, mosY + 24, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + + // Dual Screw Terminal Blocks (Right side) + double stX = boardX + boardW - 48; + g2d.setColor(SCREW_TERMINAL_COLOR); + g2d.fill(new RoundRectangle2D.Double(stX, boardY + 8, 42, 35, 3, 3)); + g2d.fill(new RoundRectangle2D.Double(stX, boardY + boardH - 43, 42, 35, 3, 3)); + + // Screw heads + g2d.setColor(Color.LIGHT_GRAY); + g2d.fill(new Ellipse2D.Double(stX + 8, boardY + 18, 12, 12)); + g2d.fill(new Ellipse2D.Double(stX + 24, boardY + 18, 12, 12)); + g2d.fill(new Ellipse2D.Double(stX + 8, boardY + boardH - 32, 12, 12)); + g2d.fill(new Ellipse2D.Double(stX + 24, boardY + boardH - 32, 12, 12)); + + // Gate Trigger Status LED (Red) + g2d.setColor(Color.RED); + g2d.fill(new RoundRectangle2D.Double(boardX + 32, boardY + boardH / 2.0 - 5, 10, 10, 2, 2)); + + // Silk Screen Pin Labels + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + String[] labels = new String[] { "SIG", "VCC", "GND" }; + double spacing = PIN_SPACING.convertToPixels(); + for (int i = 0; i < 3; i++) { + StringUtils.drawCenteredText(g2d, labels[i], x + 16, y + i * spacing, HorizontalAlignment.LEFT, VerticalAlignment.CENTER); + } + StringUtils.drawCenteredText(g2d, "VIN", stX - 10, boardY + 24, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "OUT", stX - 10, boardY + boardH - 26, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); + } + + g2d.setTransform(oldTx); + + // Draw control header pins and terminal contacts + drawPins(g2d, 0, 3, false, outlineMode, drawingObserver); + drawScrewTerminals(g2d, 3, 4, 0, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(MOSFET_RED); + g2d.fill(new RoundRectangle2D.Double(2, 4, width - 4, height - 8, 3, 3)); + g2d.setColor(Color.decode("#222222")); + g2d.fillRect(width / 2 - 4, height / 2 - 6, 8, 12); + g2d.setColor(SCREW_TERMINAL_COLOR); + g2d.fillRect(width - 10, height / 2 - 6, 8, 12); + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/modules/MT3608BoostConverter.java b/diylc/diylc-library/src/main/java/org/diylc/components/modules/MT3608BoostConverter.java new file mode 100644 index 00000000..8354b0f9 --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/modules/MT3608BoostConverter.java @@ -0,0 +1,181 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.modules; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "Boost Converter (MT3608)", category = "Modules & Breakouts", + author = "Branislav Stojkovic", description = "MT3608 2A Adjustable DC-DC Step-Up Boost Converter Module", + instanceNamePrefix = "MOD", zOrder = IDIYComponent.COMPONENT, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class MT3608BoostConverter extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color BOOST_BLUE = Color.decode("#1B4F72"); + public static Color POT_BLUE = Color.decode("#0055AA"); + + public static Size BOARD_WIDTH = new Size(36.0d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(17.0d, SizeUnit.mm); + + public MT3608BoostConverter() { + super(); + this.bodyColor = BOOST_BLUE; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double h = BOARD_HEIGHT.convertToPixels(); + double w = BOARD_WIDTH.convertToPixels(); + + // 4 Solder pads: + // Input (Left): 0 = VIN+, 1 = VIN- + // Output (Right): 2 = VOUT+, 3 = VOUT- + double[][] relativeOffsets = new double[][] { + { 0, 0 }, // Pin 0: VIN+ + { 0, h - 20 }, // Pin 1: VIN- + { w - 20, 0 }, // Pin 2: VOUT+ + { w - 20, h - 20 } // Pin 3: VOUT- + }; + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + return new RoundRectangle2D.Double(x - 10, y - 10, boardW, boardH, 6, 6); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - 10; + double boardY = y - 10; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // Power Inductor (Square SMD, Center Left) + g2d.setColor(Color.decode("#2C3E50")); + g2d.fill(new RoundRectangle2D.Double(boardX + 35, boardY + boardH / 2.0 - 20, 40, 40, 4, 4)); + g2d.setColor(Color.LIGHT_GRAY); + g2d.setFont(SILK_FONT_SMALL); + StringUtils.drawCenteredText(g2d, "220", boardX + 55, boardY + boardH / 2.0, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + + // MT3608 SOT23-6 Boost Controller IC + drawChip(g2d, boardX + 85, boardY + boardH / 2.0 - 10, 20, 20, "3608"); + + // Blue 3296W Trimmer Potentiometer (Right Center) + g2d.setColor(POT_BLUE); + g2d.fill(new RoundRectangle2D.Double(boardX + 115, boardY + 12, 45, 26, 3, 3)); + // Brass screw head + g2d.setColor(Color.decode("#D4AC0D")); + g2d.fill(new Ellipse2D.Double(boardX + 120, boardY + 19, 12, 12)); + g2d.setColor(Color.BLACK); + g2d.drawLine((int)(boardX + 122), (int)(boardY + 25), (int)(boardX + 130), (int)(boardY + 25)); + + // Silk Screen Text + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + StringUtils.drawCenteredText(g2d, "VIN+", boardX + 15, boardY + 10, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "VIN-", boardX + 15, boardY + boardH - 10, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "VOUT+", boardX + boardW - 18, boardY + 10, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "VOUT-", boardX + boardW - 18, boardY + boardH - 10, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + } + + g2d.setTransform(oldTx); + + // Draw connection pads + drawScrewTerminals(g2d, 0, controlPoints.length, 0, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(BOOST_BLUE); + g2d.fill(new RoundRectangle2D.Double(2, 6, width - 4, height - 12, 3, 3)); + g2d.setColor(Color.decode("#2C3E50")); + g2d.fillRect(6, height / 2 - 4, 8, 8); + g2d.setColor(POT_BLUE); + g2d.fillRect(width - 12, height / 2 - 4, 8, 8); + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/modules/NRF24L01Transceiver.java b/diylc/diylc-library/src/main/java/org/diylc/components/modules/NRF24L01Transceiver.java new file mode 100644 index 00000000..f01a1ce2 --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/modules/NRF24L01Transceiver.java @@ -0,0 +1,201 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.modules; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Path2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "2.4GHz RF Transceiver (NRF24L01+)", category = "Modules & Breakouts", + author = "Branislav Stojkovic", description = "NRF24L01+ 2.4GHz Wireless SPI Transceiver Module", + instanceNamePrefix = "RF", zOrder = IDIYComponent.COMPONENT, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class NRF24L01Transceiver extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color NRF_PCB = Color.decode("#111111"); + public static Color ANTENNA_GOLD = Color.decode("#D4AC0D"); + + public static Size BOARD_WIDTH = new Size(29.0d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(15.2d, SizeUnit.mm); + + public NRF24L01Transceiver() { + super(); + this.bodyColor = NRF_PCB; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double spacing = PIN_SPACING.convertToPixels(); + + // 2x4 Header (8 pins): + // Row 1 (Top): 0 = GND, 1 = CE, 2 = SCK, 3 = MISO + // Row 2 (Bottom): 4 = VCC (3.3V), 5 = CSN, 6 = MOSI, 7 = IRQ + double[][] relativeOffsets = new double[][] { + { 0, 0 }, + { spacing, 0 }, + { spacing * 2, 0 }, + { spacing * 3, 0 }, + { 0, spacing }, + { spacing, spacing }, + { spacing * 2, spacing }, + { spacing * 3, spacing } + }; + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - boardW + 4 * PIN_SPACING.convertToPixels() + 10; + double boardY = y - (boardH - PIN_SPACING.convertToPixels()) / 2.0; + return new RoundRectangle2D.Double(boardX, boardY, boardW, boardH, 4, 4); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - boardW + 4 * PIN_SPACING.convertToPixels() + 10; + double boardY = y - (boardH - PIN_SPACING.convertToPixels()) / 2.0; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // Serpentine PCB Trace Antenna (Left edge) + g2d.setColor(ANTENNA_GOLD); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(2.0f)); + Path2D antenna = new Path2D.Double(); + double ax = boardX + 8; + double ay = boardY + 12; + antenna.moveTo(ax, ay); + antenna.lineTo(ax + 35, ay); + antenna.lineTo(ax + 35, ay + 16); + antenna.lineTo(ax + 8, ay + 16); + antenna.lineTo(ax + 8, ay + 32); + antenna.lineTo(ax + 35, ay + 32); + antenna.lineTo(ax + 35, ay + 48); + antenna.lineTo(ax + 8, ay + 48); + antenna.lineTo(ax + 8, ay + 64); + antenna.lineTo(ax + 35, ay + 64); + g2d.draw(antenna); + + // NRF24L01+ QFN IC (Center) + drawChip(g2d, boardX + 60, boardY + boardH / 2.0 - 15, 30, 30, "NRF"); + + // 16.000 MHz Crystal (Silver can) + g2d.setColor(Color.decode("#BDC3C7")); + g2d.fill(new RoundRectangle2D.Double(boardX + 98, boardY + boardH / 2.0 - 10, 24, 38, 4, 4)); + g2d.setColor(Color.decode("#7F8C8D")); + g2d.draw(new RoundRectangle2D.Double(boardX + 98, boardY + boardH / 2.0 - 10, 24, 38, 4, 4)); + + // 2x4 Header Body (Black Shroud) + g2d.setColor(Color.decode("#1C1C1C")); + double spacing = PIN_SPACING.convertToPixels(); + g2d.fill(new RoundRectangle2D.Double(x - 6, y - 6, spacing * 3 + 12, spacing + 12, 3, 3)); + g2d.setColor(Color.decode("#333333")); + g2d.draw(new RoundRectangle2D.Double(x - 6, y - 6, spacing * 3 + 12, spacing + 12, 3, 3)); + + // Silk Screen Pin Labels + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + StringUtils.drawCenteredText(g2d, "NRF24L01+", boardX + boardW / 2.0, boardY + 12, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + } + + g2d.setTransform(oldTx); + + // Draw 8 header pins + drawPins(g2d, 0, controlPoints.length, false, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(NRF_PCB); + g2d.fill(new RoundRectangle2D.Double(2, 4, width - 4, height - 8, 3, 3)); + g2d.setColor(ANTENNA_GOLD); + g2d.drawLine(4, 8, 12, 8); + g2d.drawLine(12, 8, 12, 14); + g2d.drawLine(12, 14, 4, 14); + g2d.setColor(Color.GRAY); + g2d.fillRect(width - 12, height / 2 - 4, 8, 8); + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/modules/PCA9685ServoDriver.java b/diylc/diylc-library/src/main/java/org/diylc/components/modules/PCA9685ServoDriver.java new file mode 100644 index 00000000..bee85946 --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/modules/PCA9685ServoDriver.java @@ -0,0 +1,216 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.modules; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "16-Channel PWM/Servo Driver (PCA9685)", category = "Modules & Breakouts", + author = "Branislav Stojkovic", description = "PCA9685 16-Channel 12-Bit PWM I2C Servo Controller Board", + instanceNamePrefix = "MOD", zOrder = IDIYComponent.BOARD, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class PCA9685ServoDriver extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color PCA_BLUE = Color.decode("#1B4F72"); + public static Color PWM_YELLOW = Color.decode("#F1C40F"); + public static Color V_RED = Color.decode("#E74C3C"); + public static Color GND_BLACK = Color.decode("#1C1C1C"); + + public static Size BOARD_WIDTH = new Size(62.5d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(25.4d, SizeUnit.mm); + + public PCA9685ServoDriver() { + super(); + this.bodyColor = PCA_BLUE; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double spacing = PIN_SPACING.convertToPixels(); + double w = BOARD_WIDTH.convertToPixels(); + + // 60 pins total: + // Left I2C header (6 pins): 0 = GND, 1 = OE, 2 = SCL, 3 = SDA, 4 = VCC, 5 = V+ + // Right I2C cascade (6 pins): 6..11 + // 16 Servo Channels x 3 rows (GND, V+, PWM) = 48 pins (12..59) + double[][] relativeOffsets = new double[60][2]; + + // Left I2C + for (int i = 0; i < 6; i++) { + relativeOffsets[i][0] = 0; + relativeOffsets[i][1] = i * spacing; + } + + // Right I2C + for (int i = 0; i < 6; i++) { + relativeOffsets[6 + i][0] = w - 20; + relativeOffsets[6 + i][1] = i * spacing; + } + + // 16-Channel 3-row Servo header (Center area) + double startX = spacing * 2.5; + int idx = 12; + for (int col = 0; col < 16; col++) { + for (int row = 0; row < 3; row++) { + relativeOffsets[idx][0] = startX + col * spacing; + relativeOffsets[idx][1] = row * spacing + spacing * 1.5; + idx++; + } + } + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - 10; + double boardY = y - (boardH - 5 * PIN_SPACING.convertToPixels()) / 2.0; + return new RoundRectangle2D.Double(boardX, boardY, boardW, boardH, 6, 6); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - 10; + double boardY = y - (boardH - 5 * PIN_SPACING.convertToPixels()) / 2.0; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // 4 Mounting holes + drawMountingHole(g2d, boardX + 16, boardY + 16, 16); + drawMountingHole(g2d, boardX + 16, boardY + boardH - 16, 16); + drawMountingHole(g2d, boardX + boardW - 16, boardY + 16, 16); + drawMountingHole(g2d, boardX + boardW - 16, boardY + boardH - 16, 16); + + // 2-Pin Screw Terminal Block (External Servo Power V+, GND on Top Left) + g2d.setColor(SCREW_TERMINAL_COLOR); + g2d.fill(new RoundRectangle2D.Double(boardX + 45, boardY + 8, 40, 30, 3, 3)); + g2d.setColor(Color.LIGHT_GRAY); + g2d.fill(new Ellipse2D.Double(boardX + 50, boardY + 15, 12, 12)); + g2d.fill(new Ellipse2D.Double(boardX + 68, boardY + 15, 12, 12)); + + // Large Filter Electrolytic Capacitor (Top) + g2d.setColor(Color.LIGHT_GRAY); + g2d.fill(new Ellipse2D.Double(boardX + 100, boardY + 6, 32, 32)); + g2d.setColor(Color.DARK_GRAY); + g2d.draw(new Ellipse2D.Double(boardX + 100, boardY + 6, 32, 32)); + + // PCA9685 TSSOP-28 IC (Center) + drawChip(g2d, boardX + boardW / 2.0 - 25, boardY + 10, 50, 24, "PCA9685"); + + // Color-coded headers background strips for 16 channels + double spacing = PIN_SPACING.convertToPixels(); + double startX = x + spacing * 2.5; + double chanW = spacing * 16; + + g2d.setColor(GND_BLACK); + g2d.fill(new Rectangle2D.Double(startX - 8, y + spacing * 1.5 - 6, chanW + 6, 12)); + g2d.setColor(V_RED); + g2d.fill(new Rectangle2D.Double(startX - 8, y + spacing * 2.5 - 6, chanW + 6, 12)); + g2d.setColor(PWM_YELLOW); + g2d.fill(new Rectangle2D.Double(startX - 8, y + spacing * 3.5 - 6, chanW + 6, 12)); + + // Silk Screen Text + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + StringUtils.drawCenteredText(g2d, "PCA9685 16-CH SERVO DRIVER", boardX + boardW / 2.0, boardY + boardH - 10, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + } + + g2d.setTransform(oldTx); + + // Draw all 60 pins + drawPins(g2d, 0, controlPoints.length, false, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(PCA_BLUE); + g2d.fill(new RoundRectangle2D.Double(2, 4, width - 4, height - 8, 3, 3)); + g2d.setColor(PWM_YELLOW); + g2d.fillRect(6, height / 2 - 2, width - 12, 4); + g2d.setColor(V_RED); + g2d.fillRect(6, height / 2 + 2, width - 12, 4); + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/modules/RFIDRC522.java b/diylc/diylc-library/src/main/java/org/diylc/components/modules/RFIDRC522.java new file mode 100644 index 00000000..8cec79d7 --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/modules/RFIDRC522.java @@ -0,0 +1,195 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.modules; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "RFID Reader (RC522)", category = "Modules & Breakouts", + author = "Branislav Stojkovic", description = "MFRC522 13.56MHz RFID Reader/Writer SPI Module", + instanceNamePrefix = "RFID", zOrder = IDIYComponent.BOARD, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class RFIDRC522 extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color RFID_BLUE = Color.decode("#1B4F72"); + public static Color ANTENNA_GOLD = Color.decode("#D4AC0D"); + + public static Size BOARD_WIDTH = new Size(60.0d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(40.0d, SizeUnit.mm); + + public RFIDRC522() { + super(); + this.bodyColor = RFID_BLUE; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double spacing = PIN_SPACING.convertToPixels(); + + // 8-pin 0.1" header: SDA, SCK, MOSI, MISO, IRQ, GND, RST, 3.3V + double[][] relativeOffsets = new double[8][2]; + for (int i = 0; i < 8; i++) { + relativeOffsets[i][0] = 0; + relativeOffsets[i][1] = i * spacing; + } + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - boardW + 20; + double boardY = y - (boardH - 7 * PIN_SPACING.convertToPixels()) / 2.0; + return new RoundRectangle2D.Double(boardX, boardY, boardW, boardH, 8, 8); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - boardW + 20; + double boardY = y - (boardH - 7 * PIN_SPACING.convertToPixels()) / 2.0; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // 4 Mounting Holes + drawMountingHole(g2d, boardX + 16, boardY + 16, 16); + drawMountingHole(g2d, boardX + 16, boardY + boardH - 16, 16); + drawMountingHole(g2d, boardX + boardW - 40, boardY + 16, 16); + drawMountingHole(g2d, boardX + boardW - 40, boardY + boardH - 16, 16); + + // Large PCB Loop Antenna (Left side) + double antX = boardX + 25; + double antY = boardY + 20; + double antW = boardW * 0.45; + double antH = boardH - 40; + + g2d.setColor(ANTENNA_GOLD); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + for (int i = 0; i < 4; i++) { + g2d.draw(new RoundRectangle2D.Double(antX + i * 4, antY + i * 4, antW - i * 8, antH - i * 8, 4, 4)); + } + + // MFRC522 QFN IC (Center Right) + double icX = boardX + boardW * 0.62; + double icY = boardY + boardH / 2.0 - 18; + drawChip(g2d, icX, icY, 36, 36, "RC522"); + + // 27.120 MHz Crystal + g2d.setColor(Color.decode("#BDC3C7")); + g2d.fill(new RoundRectangle2D.Double(icX - 25, icY + 6, 18, 24, 3, 3)); + g2d.setColor(Color.decode("#7F8C8D")); + g2d.draw(new RoundRectangle2D.Double(icX - 25, icY + 6, 18, 24, 3, 3)); + + // Silk Screen Text + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT); + StringUtils.drawCenteredText(g2d, "RFID-RC522", antX + antW / 2.0, antY + antH / 2.0, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + + // Silk Screen Pin Labels + g2d.setFont(SILK_FONT_SMALL); + String[] labels = new String[] { "SDA", "SCK", "MOSI", "MISO", "IRQ", "GND", "RST", "3.3V" }; + double spacing = PIN_SPACING.convertToPixels(); + for (int i = 0; i < 8; i++) { + StringUtils.drawCenteredText(g2d, labels[i], boardX + boardW - 24, y + i * spacing, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); + } + } + + g2d.setTransform(oldTx); + + // Draw 8 header pins + drawPins(g2d, 0, controlPoints.length, false, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(RFID_BLUE); + g2d.fill(new RoundRectangle2D.Double(2, 2, width - 4, height - 4, 3, 3)); + g2d.setColor(ANTENNA_GOLD); + g2d.drawRect(6, 6, width / 2 - 4, height - 12); + g2d.drawRect(8, 8, width / 2 - 8, height - 16); + g2d.setColor(Color.BLACK); + g2d.fillRect(width - 12, height / 2 - 4, 8, 8); + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/modules/RotaryEncoderKY040.java b/diylc/diylc-library/src/main/java/org/diylc/components/modules/RotaryEncoderKY040.java new file mode 100644 index 00000000..a8f8a863 --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/modules/RotaryEncoderKY040.java @@ -0,0 +1,188 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.modules; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "Rotary Encoder (KY-040)", category = "Modules & Breakouts", + author = "Branislav Stojkovic", description = "KY-040 Incremental Rotary Encoder Module with Push Button", + instanceNamePrefix = "ENC", zOrder = IDIYComponent.COMPONENT, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class RotaryEncoderKY040 extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color ENCODER_PCB = Color.decode("#1B2631"); + public static Color METAL_SHAFT = Color.decode("#BDC3C7"); + + public static Size BOARD_WIDTH = new Size(32.0d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(19.0d, SizeUnit.mm); + + public RotaryEncoderKY040() { + super(); + this.bodyColor = ENCODER_PCB; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double spacing = PIN_SPACING.convertToPixels(); + + // 5-pin 0.1" header: CLK, DT, SW, +, GND + double[][] relativeOffsets = new double[5][2]; + for (int i = 0; i < 5; i++) { + relativeOffsets[i][0] = 0; + relativeOffsets[i][1] = i * spacing; + } + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - boardW + 20; + double boardY = y - (boardH - 4 * PIN_SPACING.convertToPixels()) / 2.0; + return new RoundRectangle2D.Double(boardX, boardY, boardW, boardH, 6, 6); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - boardW + 20; + double boardY = y - (boardH - 4 * PIN_SPACING.convertToPixels()) / 2.0; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // 2 Mounting Holes + drawMountingHole(g2d, boardX + 16, boardY + 16, 16); + drawMountingHole(g2d, boardX + 16, boardY + boardH - 16, 16); + + // Rotary Encoder Metal Body (Center Left) + double cx = boardX + 90; + double cy = boardY + boardH / 2.0; + + g2d.setColor(Color.decode("#7F8C8D")); + g2d.fill(new RoundRectangle2D.Double(cx - 36, cy - 36, 72, 72, 6, 6)); + + // Threaded Collar / Bushing + g2d.setColor(METAL_SHAFT); + g2d.fill(new Ellipse2D.Double(cx - 24, cy - 24, 48, 48)); + g2d.setColor(Color.decode("#95A5A6")); + g2d.draw(new Ellipse2D.Double(cx - 24, cy - 24, 48, 48)); + + // D-Shaft (Flatted center shaft) + g2d.setColor(Color.decode("#34495E")); + g2d.fill(new Ellipse2D.Double(cx - 15, cy - 15, 30, 30)); + g2d.setColor(METAL_SHAFT); + g2d.fillRect((int)(cx + 4), (int)(cy - 14), 10, 28); + + // SMD Pull-up Resistors (10k) + drawChip(g2d, boardX + 145, boardY + 25, 12, 18, ""); + drawChip(g2d, boardX + 145, boardY + boardH - 43, 12, 18, ""); + + // Silk Screen Pin Labels + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + String[] labels = new String[] { "CLK", "DT", "SW", "+", "GND" }; + double spacing = PIN_SPACING.convertToPixels(); + for (int i = 0; i < 5; i++) { + StringUtils.drawCenteredText(g2d, labels[i], boardX + boardW - 32, y + i * spacing, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); + } + } + + g2d.setTransform(oldTx); + + // Draw 5 header pins + drawPins(g2d, 0, controlPoints.length, false, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(ENCODER_PCB); + g2d.fill(new RoundRectangle2D.Double(2, 4, width - 4, height - 8, 3, 3)); + g2d.setColor(METAL_SHAFT); + g2d.fill(new Ellipse2D.Double(width / 2.0 - 8, height / 2.0 - 8, 16, 16)); + g2d.setColor(Color.decode("#34495E")); + g2d.fill(new Ellipse2D.Double(width / 2.0 - 4, height / 2.0 - 4, 8, 8)); + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/modules/TP4056Charger.java b/diylc/diylc-library/src/main/java/org/diylc/components/modules/TP4056Charger.java new file mode 100644 index 00000000..1b1932e6 --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/modules/TP4056Charger.java @@ -0,0 +1,183 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.modules; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "LiPo Charger (TP4056)", category = "Modules & Breakouts", + author = "Branislav Stojkovic", description = "TP4056 1A Li-ion Battery Charging and Protection Module", + instanceNamePrefix = "MOD", zOrder = IDIYComponent.COMPONENT, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class TP4056Charger extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color TP4056_BLUE = Color.decode("#1B4F72"); + public static Size BOARD_WIDTH = new Size(28.0d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(17.5d, SizeUnit.mm); + + public TP4056Charger() { + super(); + this.bodyColor = TP4056_BLUE; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double spacing = PIN_SPACING.convertToPixels(); + double h = BOARD_HEIGHT.convertToPixels(); + double w = BOARD_WIDTH.convertToPixels(); + + // 6 Solder pads: + // Input (Left): 0 = IN+, 1 = IN- + // Output (Right): 2 = OUT+, 3 = B+, 4 = B-, 5 = OUT- + double[][] relativeOffsets = new double[][] { + { 0, 0 }, // Pin 0: IN+ (Top-Left) + { 0, h - 20 }, // Pin 1: IN- (Bottom-Left) + { w - 20, 0 }, // Pin 2: OUT+ (Top-Right) + { w - 20, spacing }, // Pin 3: B+ + { w - 20, h - 20 - spacing }, // Pin 4: B- + { w - 20, h - 20 } // Pin 5: OUT- (Bottom-Right) + }; + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + return new RoundRectangle2D.Double(x - 10, y - 10, boardW, boardH, 6, 6); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - 10; + double boardY = y - 10; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // USB Type-C Connector (Left Edge) + drawMetalConnector(g2d, boardX - 6, boardY + boardH / 2.0 - 18, 32, 36, "Type-C"); + + // TP4056 Linear Charger IC (SOP-8) + drawChip(g2d, boardX + 60, boardY + 20, 26, 32, "4056"); + + // DW01A Battery Protection IC & Dual MOSFET + drawChip(g2d, boardX + 110, boardY + 22, 18, 20, "DW01"); + drawChip(g2d, boardX + 110, boardY + boardH - 44, 20, 24, "8205"); + + // Dual Status LEDs (Red = CHRG, Blue = STDBY) + g2d.setColor(Color.RED); + g2d.fill(new RoundRectangle2D.Double(boardX + 45, boardY + 16, 8, 12, 2, 2)); + g2d.setColor(Color.CYAN); + g2d.fill(new RoundRectangle2D.Double(boardX + 45, boardY + boardH - 28, 8, 12, 2, 2)); + + // Silk Screen Labels + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + StringUtils.drawCenteredText(g2d, "IN+", boardX + 18, boardY + 12, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "IN-", boardX + 18, boardY + boardH - 12, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "OUT+", boardX + boardW - 22, boardY + 12, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "B+", boardX + boardW - 22, boardY + 32, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "B-", boardX + boardW - 22, boardY + boardH - 32, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "OUT-", boardX + boardW - 22, boardY + boardH - 12, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + } + + g2d.setTransform(oldTx); + + // Draw solder pads + drawScrewTerminals(g2d, 0, controlPoints.length, 0, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(TP4056_BLUE); + g2d.fill(new RoundRectangle2D.Double(2, 6, width - 4, height - 12, 3, 3)); + g2d.setColor(Color.LIGHT_GRAY); + g2d.fillRect(2, height / 2 - 4, 8, 8); + g2d.setColor(Color.RED); + g2d.fill(new Ellipse2D.Double(14, height / 2 - 3, 6, 6)); + g2d.setColor(Color.CYAN); + g2d.fill(new Ellipse2D.Double(22, height / 2 - 3, 6, 6)); + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/modules/ULN2003Driver.java b/diylc/diylc-library/src/main/java/org/diylc/components/modules/ULN2003Driver.java new file mode 100644 index 00000000..4bfb23af --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/modules/ULN2003Driver.java @@ -0,0 +1,201 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.modules; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "Stepper Driver Board (ULN2003)", category = "Modules & Breakouts", + author = "Branislav Stojkovic", description = "ULN2003 Stepper Motor Driver Board with 4 Status LEDs", + instanceNamePrefix = "MOD", zOrder = IDIYComponent.BOARD, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class ULN2003Driver extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color ULN_BLUE = Color.decode("#1F618D"); + public static Color JST_WHITE = Color.decode("#EAEDED"); + public static Color LED_YELLOW = Color.decode("#F1C40F"); + + public static Size BOARD_WIDTH = new Size(35.0d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(31.5d, SizeUnit.mm); + + public ULN2003Driver() { + super(); + this.bodyColor = ULN_BLUE; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double spacing = PIN_SPACING.convertToPixels(); + + // 11 pins total: + // Pin 0..3: IN1, IN2, IN3, IN4 (Bottom left control header) + // Pin 4, 5: +5-12V, GND (Power input header) + // Pin 6..10: 5-pin JST motor socket (Top right) + double[][] relativeOffsets = new double[][] { + { 0, 0 }, + { spacing, 0 }, + { spacing * 2, 0 }, + { spacing * 3, 0 }, + { spacing * 5, 0 }, + { spacing * 6, 0 }, + // JST motor connector pins + { spacing * 4, -spacing * 7 }, + { spacing * 5, -spacing * 7 }, + { spacing * 6, -spacing * 7 }, + { spacing * 7, -spacing * 7 }, + { spacing * 8, -spacing * 7 } + }; + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - 20; + double boardY = y - boardH + 20; + return new RoundRectangle2D.Double(boardX, boardY, boardW, boardH, 6, 6); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - 20; + double boardY = y - boardH + 20; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // 4 Mounting Holes in corners + drawMountingHole(g2d, boardX + 16, boardY + 16, 16); + drawMountingHole(g2d, boardX + 16, boardY + boardH - 16, 16); + drawMountingHole(g2d, boardX + boardW - 16, boardY + 16, 16); + drawMountingHole(g2d, boardX + boardW - 16, boardY + boardH - 16, 16); + + // ULN2003A DIP-16 IC Chip (Center) + drawChip(g2d, boardX + 35, boardY + 45, 95, 42, "ULN2003A"); + + // 4 Status LEDs (A, B, C, D) + for (int i = 0; i < 4; i++) { + double lx = boardX + 42 + i * 20; + double ly = boardY + 25; + g2d.setColor(LED_YELLOW); + g2d.fill(new RoundRectangle2D.Double(lx - 5, ly - 5, 10, 10, 2, 2)); + } + + // JST-XH 5-Pin Shrouded Motor Header (Top Right) + double spacing = PIN_SPACING.convertToPixels(); + g2d.setColor(JST_WHITE); + g2d.fill(new RoundRectangle2D.Double(x + spacing * 3.5, y - spacing * 7.8, spacing * 5 + 10, spacing + 14, 3, 3)); + g2d.setColor(Color.LIGHT_GRAY); + g2d.draw(new RoundRectangle2D.Double(x + spacing * 3.5, y - spacing * 7.8, spacing * 5 + 10, spacing + 14, 3, 3)); + + // Silk Screen Text + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + StringUtils.drawCenteredText(g2d, "IN1", x, y - 12, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "IN2", x + spacing, y - 12, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "IN3", x + spacing * 2, y - 12, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "IN4", x + spacing * 3, y - 12, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "5-12V", x + spacing * 5, y - 12, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + StringUtils.drawCenteredText(g2d, "GND", x + spacing * 6, y - 12, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + } + + g2d.setTransform(oldTx); + + // Draw header pins and JST contacts + drawPins(g2d, 0, controlPoints.length, false, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(ULN_BLUE); + g2d.fill(new RoundRectangle2D.Double(2, 2, width - 4, height - 4, 3, 3)); + g2d.setColor(Color.DARK_GRAY); + g2d.fillRect(6, height / 2 - 4, width - 12, 8); + for (int i = 0; i < 4; i++) { + g2d.setColor(LED_YELLOW); + g2d.fill(new Ellipse2D.Double(6 + i * 5, 4, 3, 3)); + } + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/sensors/BME280Sensor.java b/diylc/diylc-library/src/main/java/org/diylc/components/sensors/BME280Sensor.java new file mode 100644 index 00000000..b312402e --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/sensors/BME280Sensor.java @@ -0,0 +1,174 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.sensors; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "Temp/Pressure/Humidity Sensor (BME280)", category = "Sensors", + author = "Branislav Stojkovic", description = "BME280 / BMP280 Temperature, Humidity, and Pressure Sensor (I2C/SPI)", + instanceNamePrefix = "SEN", zOrder = IDIYComponent.COMPONENT, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class BME280Sensor extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color BME_PURPLE = Color.decode("#5B2C6F"); + public static Color SENSOR_METAL = Color.decode("#C0C0C0"); + + public static Size BOARD_WIDTH = new Size(15.2d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(12.0d, SizeUnit.mm); + + public BME280Sensor() { + super(); + this.bodyColor = BME_PURPLE; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double spacing = PIN_SPACING.convertToPixels(); + + // 6-pin 0.1" header: VCC, GND, SCL, SDA, CSB, SDO + double[][] relativeOffsets = new double[6][2]; + for (int i = 0; i < 6; i++) { + relativeOffsets[i][0] = i * spacing; + relativeOffsets[i][1] = 0; + } + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - (boardW - 5 * PIN_SPACING.convertToPixels()) / 2.0; + double boardY = y - 16; + return new RoundRectangle2D.Double(boardX, boardY, boardW, boardH, 4, 4); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - (boardW - 5 * PIN_SPACING.convertToPixels()) / 2.0; + double boardY = y - 16; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // 1 Mounting Hole (Right side) + drawMountingHole(g2d, boardX + boardW - 16, boardY + boardH - 20, 14); + + // BME280 Metal Sensor Can with vent hole (Center) + double sx = boardX + 35; + double sy = boardY + boardH - 35; + g2d.setColor(SENSOR_METAL); + g2d.fill(new RoundRectangle2D.Double(sx, sy, 24, 20, 2, 2)); + g2d.setColor(Color.DARK_GRAY); + g2d.draw(new RoundRectangle2D.Double(sx, sy, 24, 20, 2, 2)); + // Vent hole + g2d.setColor(Color.BLACK); + g2d.fill(new Ellipse2D.Double(sx + 5, sy + 5, 4, 4)); + + // LDO Voltage Regulator (Left) + drawChip(g2d, boardX + 12, boardY + boardH - 32, 16, 16, ""); + + // Silk Screen Text + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + StringUtils.drawCenteredText(g2d, "BME280", boardX + boardW / 2.0, boardY + 18, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + } + + g2d.setTransform(oldTx); + + // Draw 6 header pins + drawPins(g2d, 0, controlPoints.length, false, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(BME_PURPLE); + g2d.fill(new RoundRectangle2D.Double(2, 4, width - 4, height - 8, 3, 3)); + g2d.setColor(SENSOR_METAL); + g2d.fill(new RoundRectangle2D.Double(width / 2 - 5, height / 2 - 4, 10, 8, 2, 2)); + g2d.setColor(Color.BLACK); + g2d.fill(new Ellipse2D.Double(width / 2 - 3, height / 2 - 2, 2, 2)); + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/sensors/SoilMoistureSensor.java b/diylc/diylc-library/src/main/java/org/diylc/components/sensors/SoilMoistureSensor.java new file mode 100644 index 00000000..ed62773b --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/sensors/SoilMoistureSensor.java @@ -0,0 +1,196 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.sensors; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Path2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "Soil Moisture Sensor (Capacitive)", category = "Sensors", + author = "Branislav Stojkovic", description = "Capacitive Corrosion-Resistant Soil Moisture Sensor Module", + instanceNamePrefix = "SEN", zOrder = IDIYComponent.COMPONENT, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class SoilMoistureSensor extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color SOIL_PCB = Color.decode("#17202A"); + public static Color PROBE_TRACE = Color.decode("#273746"); + + public static Size BOARD_WIDTH = new Size(60.0d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(20.0d, SizeUnit.mm); + + public SoilMoistureSensor() { + super(); + this.bodyColor = SOIL_PCB; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double spacing = PIN_SPACING.convertToPixels(); + + // 3-pin 0.1" header on handle: VCC, GND, AOUT + double[][] relativeOffsets = new double[][] { + { 0, 0 }, + { 0, spacing }, + { 0, spacing * 2 } + }; + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - 15; + double boardY = y - (boardH - 2 * PIN_SPACING.convertToPixels()) / 2.0; + + Path2D path = new Path2D.Double(); + path.moveTo(boardX, boardY); + path.lineTo(boardX + boardW * 0.35, boardY); + path.lineTo(boardX + boardW - 15, boardY + 4); + path.lineTo(boardX + boardW, boardY + boardH / 2.0); + path.lineTo(boardX + boardW - 15, boardY + boardH - 4); + path.lineTo(boardX + boardW * 0.35, boardY + boardH); + path.lineTo(boardX, boardY + boardH); + path.closePath(); + return path; + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - 15; + double boardY = y - (boardH - 2 * PIN_SPACING.convertToPixels()) / 2.0; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // Capacitive Sensing Copper Area (Right blade section) + double bladeX = boardX + boardW * 0.38; + double bladeW = boardW * 0.55; + g2d.setColor(PROBE_TRACE); + g2d.fill(new RoundRectangle2D.Double(bladeX, boardY + 12, bladeW, boardH - 24, 6, 6)); + + // White silk dividing line & warning + g2d.setColor(Color.WHITE); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); + g2d.drawLine((int)(boardX + boardW * 0.35), (int)boardY + 4, (int)(boardX + boardW * 0.35), (int)(boardY + boardH - 4)); + + // NE555 / TLC555 Oscillator Timer IC (Handle area) + drawChip(g2d, boardX + 45, boardY + boardH / 2.0 - 14, 28, 28, "555"); + + // 3.3V Voltage Regulator + drawChip(g2d, boardX + 85, boardY + boardH / 2.0 - 10, 18, 20, ""); + + // Silk Screen Text + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + StringUtils.drawCenteredText(g2d, "Capacitive Soil Sensor v1.2", bladeX + bladeW / 2.0, boardY + boardH / 2.0, HorizontalAlignment.CENTER, VerticalAlignment.CENTER); + + // Pin labels + String[] labels = new String[] { "VCC", "GND", "AOUT" }; + double spacing = PIN_SPACING.convertToPixels(); + for (int i = 0; i < 3; i++) { + StringUtils.drawCenteredText(g2d, labels[i], x + 16, y + i * spacing, HorizontalAlignment.LEFT, VerticalAlignment.CENTER); + } + } + + g2d.setTransform(oldTx); + + // Draw 3 header pins + drawPins(g2d, 0, controlPoints.length, false, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(SOIL_PCB); + Path2D p = new Path2D.Double(); + p.moveTo(2, 6); + p.lineTo(width - 10, 6); + p.lineTo(width - 2, height / 2.0); + p.lineTo(width - 10, height - 6); + p.lineTo(2, height - 6); + p.closePath(); + g2d.fill(p); + g2d.setColor(PROBE_TRACE); + g2d.fillRect(width / 2, 8, width / 2 - 8, height - 16); + } +} diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/sensors/TCRT5000Sensor.java b/diylc/diylc-library/src/main/java/org/diylc/components/sensors/TCRT5000Sensor.java new file mode 100644 index 00000000..72bc2123 --- /dev/null +++ b/diylc/diylc-library/src/main/java/org/diylc/components/sensors/TCRT5000Sensor.java @@ -0,0 +1,188 @@ +/* + * + * DIY Layout Creator (DIYLC). + * Copyright (c) 2009-2025 held jointly by the individual authors. + * + * This file is part of DIYLC. + * + * DIYLC is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * DIYLC is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with DIYLC. If not, see . + * + */ +package org.diylc.components.sensors; + +import java.awt.Color; +import java.awt.Composite; +import java.awt.Graphics2D; +import java.awt.Shape; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.geom.RoundRectangle2D; + +import org.diylc.awt.StringUtils; +import org.diylc.common.HorizontalAlignment; +import org.diylc.common.ObjectCache; +import org.diylc.common.Orientation; +import org.diylc.common.VerticalAlignment; +import org.diylc.components.AbstractMakerBoard; +import org.diylc.core.ComponentState; +import org.diylc.core.IDIYComponent; +import org.diylc.core.IDrawingObserver; +import org.diylc.core.Project; +import org.diylc.core.annotations.BomPolicy; +import org.diylc.core.annotations.ComponentDescriptor; +import org.diylc.core.annotations.KeywordPolicy; +import org.diylc.core.measures.Size; +import org.diylc.core.measures.SizeUnit; +import org.diylc.utils.Constants; + +@ComponentDescriptor(name = "Line / Obstacle Sensor (TCRT5000)", category = "Sensors", + author = "Branislav Stojkovic", description = "TCRT5000 Infrared Line Tracking and Optical Obstacle Avoidance Sensor", + instanceNamePrefix = "SEN", zOrder = IDIYComponent.COMPONENT, + bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME, + enableCache = true) +public class TCRT5000Sensor extends AbstractMakerBoard { + + private static final long serialVersionUID = 1L; + + public static Color SENSOR_BLUE = Color.decode("#1B4F72"); + public static Color POT_BLUE = Color.decode("#0055AA"); + + public static Size BOARD_WIDTH = new Size(32.0d, SizeUnit.mm); + public static Size BOARD_HEIGHT = new Size(14.0d, SizeUnit.mm); + + public TCRT5000Sensor() { + super(); + this.bodyColor = SENSOR_BLUE; + updateControlPoints(); + } + + @Override + protected void updateControlPoints() { + Point2D firstPoint = controlPoints[0]; + double spacing = PIN_SPACING.convertToPixels(); + + // 4-pin 0.1" header: VCC, GND, DO, AO + double[][] relativeOffsets = new double[4][2]; + for (int i = 0; i < 4; i++) { + relativeOffsets[i][0] = 0; + relativeOffsets[i][1] = i * spacing; + } + + rotatePoints(firstPoint, relativeOffsets); + } + + @Override + public Shape getBodyShape() { + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - boardW + 20; + double boardY = y - (boardH - 3 * PIN_SPACING.convertToPixels()) / 2.0; + return new RoundRectangle2D.Double(boardX, boardY, boardW, boardH, 4, 4); + } + + @Override + public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, + IDrawingObserver drawingObserver) { + if (checkPointsClipped(g2d.getClip())) { + return; + } + + Point2D p0 = controlPoints[0]; + double x = p0.getX(); + double y = p0.getY(); + + AffineTransform oldTx = g2d.getTransform(); + if (orientation != Orientation.DEFAULT) { + g2d.rotate(orientation.toRadians(), x, y); + } + + double boardW = BOARD_WIDTH.convertToPixels(); + double boardH = BOARD_HEIGHT.convertToPixels(); + double boardX = x - boardW + 20; + double boardY = y - (boardH - 3 * PIN_SPACING.convertToPixels()) / 2.0; + + Shape boardShape = getBodyShape(); + + Composite oldComposite = applyAlpha(g2d, componentState); + + drawingObserver.startTracking(); + g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : bodyColor); + g2d.fill(boardShape); + drawingObserver.stopTracking(); + + g2d.setColor(getFinalBorderColor(componentState, outlineMode)); + g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1.5f)); + g2d.draw(boardShape); + + if (!outlineMode) { + // TCRT5000 Optical Package (Left Edge) + g2d.setColor(Color.decode("#2C3E50")); + g2d.fill(new RoundRectangle2D.Double(boardX - 10, boardY + boardH / 2.0 - 20, 36, 40, 4, 4)); + // Blue IR LED + g2d.setColor(Color.decode("#3498DB")); + g2d.fill(new Ellipse2D.Double(boardX - 6, boardY + boardH / 2.0 - 15, 14, 14)); + // Black Phototransistor + g2d.setColor(Color.BLACK); + g2d.fill(new Ellipse2D.Double(boardX - 6, boardY + boardH / 2.0 + 1, 14, 14)); + + // LM393 Comparator IC (Center) + drawChip(g2d, boardX + 45, boardY + boardH / 2.0 - 14, 30, 28, "393"); + + // Sensitivity Trimmer Potentiometer (Right Center) + g2d.setColor(POT_BLUE); + g2d.fill(new RoundRectangle2D.Double(boardX + 90, boardY + boardH / 2.0 - 16, 32, 32, 3, 3)); + g2d.setColor(Color.decode("#BDC3C7")); + g2d.fill(new Ellipse2D.Double(boardX + 96, boardY + boardH / 2.0 - 10, 20, 20)); + g2d.setColor(Color.BLACK); + g2d.drawLine((int)(boardX + 99), (int)(boardY + boardH / 2.0), (int)(boardX + 113), (int)(boardY + boardH / 2.0)); + + // Status LEDs (Power & Signal) + g2d.setColor(Color.RED); + g2d.fill(new RoundRectangle2D.Double(boardX + 135, boardY + 12, 10, 8, 2, 2)); + g2d.setColor(Color.GREEN); + g2d.fill(new RoundRectangle2D.Double(boardX + 135, boardY + boardH - 20, 10, 8, 2, 2)); + + // Silk Screen Pin Labels + g2d.setColor(Color.WHITE); + g2d.setFont(SILK_FONT_SMALL); + String[] labels = new String[] { "VCC", "GND", "DO", "AO" }; + double spacing = PIN_SPACING.convertToPixels(); + for (int i = 0; i < 4; i++) { + StringUtils.drawCenteredText(g2d, labels[i], boardX + boardW - 24, y + i * spacing, HorizontalAlignment.RIGHT, VerticalAlignment.CENTER); + } + } + + g2d.setTransform(oldTx); + + // Draw 4 header pins + drawPins(g2d, 0, controlPoints.length, false, outlineMode, drawingObserver); + + g2d.setComposite(oldComposite); + } + + @Override + public void drawIcon(Graphics2D g2d, int width, int height) { + g2d.setColor(SENSOR_BLUE); + g2d.fill(new RoundRectangle2D.Double(2, 4, width - 4, height - 8, 3, 3)); + g2d.setColor(Color.CYAN); + g2d.fill(new Ellipse2D.Double(4, height / 2 - 6, 6, 6)); + g2d.setColor(Color.BLACK); + g2d.fill(new Ellipse2D.Double(4, height / 2, 6, 6)); + } +} diff --git a/diylc/diylc-library/src/test/java/org/diylc/components/maker/MakerComponentsTest.java b/diylc/diylc-library/src/test/java/org/diylc/components/maker/MakerComponentsTest.java index fa21cb5c..ffd91539 100644 --- a/diylc/diylc-library/src/test/java/org/diylc/components/maker/MakerComponentsTest.java +++ b/diylc/diylc-library/src/test/java/org/diylc/components/maker/MakerComponentsTest.java @@ -75,6 +75,9 @@ public class MakerComponentsTest { DHTSensor.class, MPU6050.class, LDRSensorModule.class, + BME280Sensor.class, + SoilMoistureSensor.class, + TCRT5000Sensor.class, // Displays & Outputs CharacterLCD.class, @@ -82,6 +85,7 @@ public class MakerComponentsTest { SevenSegmentDisplay.class, LEDMatrix8x8.class, TFTDisplay.class, + WS2812BStick.class, // Modules & Breakouts LogicLevelConverter.class, @@ -90,6 +94,18 @@ public class MakerComponentsTest { RelayModule.class, SDCardModule.class, RTCModule.class, + MB102PowerSupply.class, + TP4056Charger.class, + LM2596BuckConverter.class, + MT3608BoostConverter.class, + AnalogJoystickKY023.class, + RotaryEncoderKY040.class, + NRF24L01Transceiver.class, + HC05Bluetooth.class, + RFIDRC522.class, + ULN2003Driver.class, + PCA9685ServoDriver.class, + MOSFETSwitchModule.class, // Robotics MicroServoSG90.class,