Skip to the content
2 layers191.3 × 181.7 mmIO Card G3, the printed circuit board in 3D

This is my custom I/O card, third generation. Main purpose is to serve as an alarm system.

Size
191.3 × 181.7 mm
Copper layers
2
Thickness
1.6 mm
Parts
400
Nets
276
Pads
1,105
Tracks, vias
4,483, 893
Pours
3
Routed
Yes
KiCad
KiCad 5 (file 20171130)
Created
1 Aug 2018
Updated
29 Mar 2024

Overview

IO Card G3 is an open-source printed circuit board by PerMalmberg, from the PerMalmberg/IO-Card-G3 repository on GitHub, published under the MIT licence. It is a 2-layer board of 191.3 × 181.7 mm with 400 parts on 276 nets, routed with 4,483 tracks and 893 vias.

It is built around the ESP32-WROVER-B, SN74LV4T125PW and ADS1115IDGST, with the BME280, LTV-354T and MCP23017-E/SS among its other parts. Its parts include 146 resistors, 89 diodes, 40 connectors, 39 capacitors and 27 fuses. It belongs with the ESP32 boards of this library.

Main components

12

README

README.md

IO-Card G3

This is my custom I/O card, third generation. Main purpose is to serve as an alarm system.

Hardware features

  • 8 analog inputs for detecting changes in resistance (a.k.a balanced line).
  • 8 digital inputs, 3.3-24V
  • 8 digital outputs, 5/12V, fused.
  • 6 controllable status LED.
  • Optional BME280
  • Wiegand interface
  • On-board buzzer.
  • SD Card (SPI and MMC bus selectable)
  • JTAG debugging (when SD Card is using SPI)
  • LED indicators for all input and outputs.
  • Screw terminals for all interfaces.
  • MCU: ESP32 Wrover Module
  • Powered by 12V DC.

Software

  • Web interface for configuration and status monitoring.
  • MQTT for control and monitoring.

Software overview

Feature specification / task list
  • NTP Based on config, synchronize clock with NTP server every 15 minutes.
  • I2C
    • On interrupt on ANALOG_RDY_1 or ANALOG_RDY_2, read analog values; publish internally.
    • On interrupt on DIA_Interrupt, read digital input values; publish internally.
    • Periodically read BME280 values and publish internally (<id>/io/status/sensor)
    • Receive control events and set digital outputs accordingly.
      • Also handle SIREN_CTRL, even though it is not on the I2C bus.
  • MQTT
    • All payloads must be JSON-formated.
    • Periodically publish all I/O statuses on the following topics:
      • <ID>/io/status/digital/input/<number>
      • <ID>/io/status/digital/output/<number>
      • <ID>/io/status/analog/input/<number>
      • <ID>/io/status/buzzer
      • <ID>/io/status/siren
      • Publish Wiegand button sequences on topic <ID>/io/status/wiegand
      • If enabled in configuration, allow I/O to be controlled via topic <ID>/io/set/channel_no, where channel_no is a number between 0 and 7.
    • All published items shall have a unix_timestamp value which tells when the item was created.
    • a value of true shall be interpreted as 'active', regardless if the input/output is active high or low. i.e. if the buzzer is making sounds, the the status is true.
    • All topics can be renamed via configuration.
      • The special string @ID@ is used to signify the ID of the device. Any instance of it in the replacement topic will be replaced with the device ID.
      • Once a topic is renamed, the original one ceases to function until the renaming is removed from the configuration.
  • Wiegand
    • Listen to button presses and publish internally.
    • Each series must end with the execute_button button, usually '#' (but as its numerical button value). Any press on the cancel_button (*) clears any already entered numbers from the buffer.
    • If no input is received during entry_timeout milliseconds, the bufer is cleared and no number series is published.
  • Alarm
    • Based on configuration, do:
      • Play sound using the buzzer when any armed I/O with an entry_delay larger than 0 changes state, for the duration of the delay.
      • Sound siren for X minutes when any input marked as armed no longer matches its configured armed_state. For analog inputs this means a value outside the range of value +/- allowed_hysteresis.
        • Delay for the configured entry_delay if the triggering input has one larger than 0. Immediately sound the siren if an input other than the first is triggered during the wait time.
      • Silence siren after X minutes, regardless if an IO marked as armed has returned to its armed_state or not.
        • Do not sound the siren again until after Y minutes.
      • Inputs with active set to false are never considered for any operation.
Startup procedure
  • Initialize I2C Bus.
    • 2x MCP23017
    • 2x ADS1115IDGST
    • Optional BME280.
  • Read SD_ENABLE to determine the mode for the SD Card.
    • Initialize SD Card.
      • If initialization fails, pause for a short amount of time and retry X times.
      • If initialization fails Y times, power cycle SD Card and try again.
  • Read device ID from configuration.
    • If not set, generate a random number and set ID to IOG3_<number>.
  • Start Wifi
  • Start MQTT worker
  • Start I2C worker
  • Start Wiegand worker
  • Start Alarm worker

Rendering of the PCB

(sorry, no 3D models for some components)

PCB Rendering

Configuration file examples

alarm.jsn

json
{
	"sensors":	{
		"digital":	{
			"input":	{
				"0":	{
					"name":	"D0",
					"enabled":	true,
					"armed_state":	true,
					"entry_delay":	5,
					"exit_delay":	5
				},
				"1":	{
					"name":	"1",
					"enabled":	false,
					"armed_state":	true,
					"entry_delay":	0,
					"exit_delay":	0
				},
				"2":	{
					"name":	"2",
					"enabled":	false,
					"armed_state":	true,
					"entry_delay":	0,
					"exit_delay":	0

dev_id.jsn

json
{
	"device_id":	"g3"
}

mqtt.jsn

json
{
	"keep_alive_seconds":	15,
	"broker":	{
		"address":	"1.2.3.4",
		"port":	1883
	}
}

notes.jsn

json
{
	"entry_delay": {
		"signal": [500, 500],
		"repeat": true
	},
	"exit_delay": {
		"signal": [1500, 500],
		"repeat": true
	},
	"error": {
		"signal": [250, 250, 250, 250, 250],
		"repeat": false
	},
	"armed": {
		"signal": [800, 200, 800, 200, 800],
		"repeat": false
	},
	"disarmed": {
		"signal": [800, 200, 800, 200],
		"repeat": false
	},
	"key_entry_timeout": {
		"signal": [200, 200, 200, 200, 200, 200],
		"repeat": false
	}
}

sntp.jsn

text
{
	"sntp_servers":	["0.se.pool.ntp.org", "1.se.pool.ntp.org", "2.se.pool.ntp.org"]
}

wifi.jsn

json
{
	"ssid":	"Your SSID",
	"password":	"Your password"
}

Parts

400
QtyValueFootprintReferences
331.65kResistor_SMD:R_0805_2012MetricR1401, R1402, R1403, R1404, R1405, R1406, R1407, R1408, R1409, R1410, R1411, R1412, R1502, R1603, R1703, R1803 +17
3110kResistor_SMD:R_0805_2012MetricR301, R302, R303, R1504, R1605, R1705, R1805, R1905, R2005, R2105, R2205, R2305, R2401, R2804, R2904, R3004 +15
27100nCapacitor_SMD:C_0805_2012MetricC201, C202, C203, C204, C301, C302, C304, C305, C306, C307, C1001, C1101, C1201, C1301, C1401, C1402 +11
21470Resistor_SMD:R_0805_2012MetricR1601, R1604, R1701, R1704, R1801, R1804, R1901, R1904, R2001, R2004, R2101, R2104, R2201, R2204, R2301, R2304 +5
20CZRQR52C6V8-HFDiode_SMD:D_0402_1005MetricD1602, D1603, D1702, D1703, D1802, D1803, D1902, D1903, D2002, D2003, D2102, D2103, D2202, D2203, D2302, D2303 +4
20RedLED_THT:LED_D5.0mmD201, D206, D207, D1402, D1403, D1405, D1406, D1408, D1409, D1411, D1412, D1501, D2801, D2901, D3001, D3101 +4
17xAFuse:Fuseholder_TR5_Littlefuse_No560_No460F201, F202, F203, F1501, F2801, F2901, F3001, F3101, F3201, F3301, F3401, F3501, F3502, F3503, F3504, F3505 +1
16100Resistor_SMD:R_0805_2012MetricR603, R703, R803, R903, R1003, R1103, R1203, R1303, R1503, R2803, R2903, R3003, R3103, R3203, R3303, R3403
16STPS0560ZDiode_SMD:D_SOD-123D602, D603, D702, D703, D802, D803, D902, D903, D1002, D1003, D1102, D1103, D1202, D1203, D1302, D1303
11GreenLED_THT:LED_D5.0mmD1601, D1701, D1801, D1901, D2001, D2101, D2201, D2301, D2401, D3202, D3302
11Si2312CDPackage_TO_SOT_SMD:SOT-23Q1601, Q1701, Q1801, Q1901, Q2001, Q2101, Q2201, Q2301, Q2401, Q3201, Q3301
11Si2323CDSPackage_TO_SOT_SMD:SOT-23Q1602, Q1702, Q1802, Q1902, Q2002, Q2102, Q2202, Q2302, Q2402, Q3202, Q3302
102.2kResistor_SMD:R_0805_2012MetricR1602, R1702, R1802, R1902, R2002, R2102, R2202, R2302, R3208, R3308
10Power_selectConnector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_VerticalJ1601, J1701, J1801, J1901, J2001, J2101, J2201, J2301, J3203, J3303
10xAFuse:Fuseholder_TR5_Littelfuse_No560_No460F1601, F1701, F1801, F1901, F2001, F2101, F2201, F2301, F3202, F3302
910uCapacitor_SMD:CP_Elec_5x4.5C402, C1501, C2801, C2901, C3001, C3101, C3201, C3301, C3401
81kResistor_SMD:R_2512_6332MetricR1501, R2801, R2901, R3001, R3101, R3201, R3301, R3401
81kResistor_SMD:R_0805_2012MetricR601, R701, R801, R901, R1001, R1101, R1201, R1301
82kResistor_SMD:R_0805_2012MetricR602, R702, R802, R902, R1002, R1102, R1202, R1302
8B72510E250K062Capacitor_SMD:C_0805_2012MetricRV601, RV701, RV801, RV901, RV1001, RV1101, RV1201, RV1301
8CDBA3100-HFDiode_SMD:D_SMAD601, D701, D801, D901, D1001, D1101, D1201, D1301
8Digital input GNDConnector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_VerticalJ1502, J2802, J2902, J3002, J3102, J3202, J3302, J3402
8Digital input supplyConnector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_VerticalJ1501, J2801, J2901, J3001, J3101, J3201, J3301, J3401
8LTV-354TPackage_SO:SO-4_4.4x3.6mm_P2.54mmU1501, U2801, U2901, U3001, U3101, U3201, U3301, U3401
650kResistor_SMD:R_0805_2012MetricR401, R402, R403, R404, R405, R406
6D_TVSDiode_SMD:D_0603_1608MetricD402, D403, D404, D405, D406, D407
4MountingHoleMountingHole:MountingHole_4.3mm_M4MH101, MH102, MH103, MH104
2100uCapacitor_THT:CP_Radial_D6.3mm_P2.50mmC205, C206
2120Resistor_SMD:R_0805_2012MetricR2403, R2405
2ADS1115IDGSTPackage_SO:TSSOP-10_3x3mm_P0.5mmU501, U502
2Digital inputPerMalmberg:MOLEX_1x9_39544-3009J3504, J3506
2Digital outputPerMalmberg:MOLEX_1x9_39544-3009J3508, J3509
2GS2Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_VerticalJ202, J203
2MCP23017Package_SO:SOIC-28W_7.5x17.9mm_P1.27mmU1401, U1402
2RBR3MM30ATRDiode_SMD:D_SOD-123FD202, D203
2SensePerMalmberg:MOLEX_1x9_39544-3009J3501, J3503
12.55kResistor_SMD:R_0805_2012MetricR203
122uCapacitor_SMD:C_0805_2012MetricC303
13.3VDiode_SMD:D_SOD-123D204
14.7kResistor_SMD:R_0805_2012MetricR2404
15.1VDiode_SMD:D_SOD-123D205
16.04kResistor_SMD:R_0805_2012MetricR201
1BME280Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_VerticalJ302
1Boot optionButton_Switch_SMD:SW_SPST_CK_KXT3SW301
1DebugConnector_PinHeader_2.54mm:PinHeader_2x05_P2.54mm_VerticalJ301
1Digital InputPerMalmberg:MOLEX_1x9_39544-3009J3502
1Digital OutputPerMalmberg:MOLEX_1x9_39544-3009J3507
1EMI_Filter_LCLConnector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_VerticalFL201
1ESP32_WROVERPerMalmberg:ESP32_WROVERU301
1Factory resetButton_Switch_SMD:SW_SPST_CK_KXT3SW303
1LM1084-3.3Package_TO_SOT_SMD:TO-263-3_TabPin2U201
1LM1084-5.0Package_TO_SOT_SMD:TO-263-3_TabPin2U202
1Logo_Open_Hardware_SmallSymbol:OSHW-Logo2_7.3x6mm_SilkScreenLOGO101
1MAX4948Package_DFN_QFN:QFN-24-1EP_4x4mm_P0.5mm_EP2.6x2.6mm_ThermalViasU401
1MQTT ConnectedLED_THT:LED_D5.0mmD1410
1Micro_SD_Card_DetConnector_Card:microSD_HC_Hirose_DM3AT-SF-PEJM5J401
1Power 12/5/3PerMalmberg:MOLEX_1x9_39544-3009J3505
1ResetButton_Switch_SMD:SW_SPST_CK_KXT3SW302
1SD SPI/MMC modeButton_Switch_SMD:SW_DIP_SPSTx02_Slide_Omron_A6S-210x_W8.9mm_P2.54mmSW1
1SDC1610M5-01PerMalmberg:SDC1610M5-01_Buzzer_16diam_5pitchBZ1401
1SDCard Init OKLED_THT:LED_D5.0mmD1401
1SN74LV4T125Package_SO:TSSOP-14_4.4x5mm_P0.65mmU302
1SNTP Time setLED_THT:LED_D5.0mmD1407
1Wifi ConnectedLED_THT:LED_D5.0mmD1404
1ZXTN25050DFHTAPackage_TO_SOT_SMD:SOT-23Q401

Similar boards

  • 2 layers156.2 × 187.5 mmIO Card G2, the printed circuit board in 3D

    IO Card G2

    PerMalmberg/IO-Card-G2

    I/O card, generation 2

    232 partsMIT
  • 2 layers72.3 × 36.1 mmMultichannel led driver, the printed circuit board in 3D

    Multichannel led driver

    rossuthoff/multichannel_led_driver

    LED driver for up to nine LED strings

    340 parts1GPL-3.0
  • 4 layers50 × 50 mmBoard v1, the printed circuit board in 3D

    Board v1

    ductomn/Swarm-robot

    Bachelor Thesis - Design and implementation of a cooperative robotic platform with simple communication

    79 parts
  • 4 layers96 × 42.2 mmCANDrive, the printed circuit board in 3D

    CANDrive

    Andreasdahlberg/CANDrive

    CANDrive is a brushed DC Motor Controller controlled via a CAN interface.

    80 parts3GPL-3.0
  • 4 layers96 × 42.2 mmCandrive, the printed circuit board in 3D

    Candrive

    Andreasdahlberg/CANDriveHW

    CANDrive is a brushed DC Motor Controller controlled via a CAN interface.

    70 partsCC0-1.0

Questions

How big is the IO Card G3 PCB?

It measures 191.3 × 181.7 mm and has 2 copper layers, 1.6 mm thick.

What parts does the IO Card G3 use?

400 parts, built around the ESP32-WROVER-B, SN74LV4T125PW, ADS1115IDGST and BME280. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the IO Card G3 KiCad files?

From the PerMalmberg/IO-Card-G3 repository on GitHub, at the commit this page was made from: the board is hardware/G3.kicad_pcb. PCBKit opens the board in the browser, with nothing to install.

Can I use the IO Card G3 design in my own project?

Its repository publishes it under the MIT licence: you may reuse it on that licence's terms (keep the author's notice, and for a copyleft licence share your changes alike).