diff --git a/content/hardware/07.opta/opta-family/opta-analog-exp/compatibility.yml b/content/hardware/07.opta/opta-family/opta-analog-exp/compatibility.yml
new file mode 100644
index 0000000000..956972eba6
--- /dev/null
+++ b/content/hardware/07.opta/opta-family/opta-analog-exp/compatibility.yml
@@ -0,0 +1,5 @@
+software:
+ - arduino-ide
+ - arduino-cli
+ - iot-cloud
+ - plc-ide
\ No newline at end of file
diff --git a/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/assets/Opta_Digital_EXP_Block_Diagram.svg b/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/assets/Opta_Digital_EXP_Block_Diagram.svg
new file mode 100644
index 0000000000..b010539f45
--- /dev/null
+++ b/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/assets/Opta_Digital_EXP_Block_Diagram.svg
@@ -0,0 +1,83 @@
+
diff --git a/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/assets/dimensions.png b/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/assets/dimensions.png
new file mode 100644
index 0000000000..d616e65989
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/assets/dimensions.png differ
diff --git a/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/assets/featured.png b/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/assets/featured.png
new file mode 100644
index 0000000000..12ce83d004
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/assets/featured.png differ
diff --git a/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/assets/parts.png b/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/assets/parts.png
new file mode 100644
index 0000000000..90f4d2ff86
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/assets/parts.png differ
diff --git a/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/assets/rtd-3wires.png b/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/assets/rtd-3wires.png
new file mode 100644
index 0000000000..5c6b3aa88f
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/assets/rtd-3wires.png differ
diff --git a/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/datasheet.md b/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/datasheet.md
new file mode 100644
index 0000000000..3436b5815f
--- /dev/null
+++ b/content/hardware/07.opta/opta-family/opta-analog-exp/datasheet/datasheet.md
@@ -0,0 +1,339 @@
+---
+identifier: AFX00007
+title: Arduino Opta® Analog Expansion
+type: pro
+author: Christopher Méndez
+---
+
+
+# Description
+Arduino Opta® Analog Expansions are designed to multiply your Opta® micro PLC capabilities with the addition of 8 channels that can be programmed as inputs or outputs for connecting your analog voltage, current, resistive temperature sensors or actuators in addition to 4x dedicated PWM outputs. Designed in partnership with leading relay manufacturer Finder®, it allows professionals to scale up industrial and building automation projects while taking advantage of the Arduino ecosystem.
+
+
+# Target Areas:
+Industrial IoT, Building automation, Electrical loads management, Industrial automation
+
+# CONTENTS
+
+## Application Examples
+The Arduino Opta® Analog Expansion is designed for industrial standard machinery control alongside the Opta® micro PLC. It is readily integrated into the Arduino hardware and software ecosystem.
+
+- **Automated Production Line:** Arduino Opta® can manage the overall flow of goods in manufacturing. For example, by integrating a load cell or a vision system, it can ensure each phase of a packing process is performed correctly, automatically discard faulty parts, ensure the appropriate amount of goods is present within each box and interact with production line printers, also adding timestamp information synchronized via Network Time Protocol (NTP).
+
+- **Real-time Monitoring in Manufacturing:** Production data can be visualized locally via an HMI or even by connecting to the Arduino Opta® via Bluetooth® Low Energy. The simplicity of Arduino Cloud allows to remotely display custom dashboards; this product is also compatible with other major Cloud providers.
+
+- **Automated Anomaly Detection:** Its computing power allows the Arduino Opta® to deploy Machine Learning algorithms that are capable to learn when a process is drifting from its usual behavior on the production line and activating/deactivating processes to prevent equipment damage.
+
+## Features
+### General Specifications Overview
+
+| Characteristics | Details |
+| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Supply Voltage | 12...24 V |
+| Reverse polarity protection | Yes |
+| ESP protection | Yes |
+| Overvoltage protection | Yes (up to 40 V) |
+| Channels | 8x: I1, I2, I3, I4, O1, I5, I6, O2 |
+| Channels functionalities | I1 and I2: Programmable inputs (Voltage, Current, RTD2 wires, RTD3 wires), Programmable outputs (Voltage and current) - I3, I4, O1, I5, I6, O2: Programmable inputs (Voltage, Current, RTD2 wires), Programmable outputs (Voltage and current) |
+| Degree of Protection | IP20 |
+| Certifications | FCC, CE, UKCA, cULus, ENEC |
+
+
+Note: Check the inputs and outputs detailed sections below for more information about the Analog Expansion channels use.
+
+
+### Inputs
+
+| Characteristics | Details |
+| ------------------------------- | ----------------------------------------------------- |
+| Number of channels | 8x |
+| Channels programmable as inputs | I1, I2, I3, I4, O1, I5, I6, O2 |
+| Type of inputs accepted | Digital Voltage and Analog (Voltage, Current and RTD) |
+| Inputs overvoltage protection | Yes (Up to 40 V) |
+| Antipolarity protection | No |
+| Analog Input resolution | 16 bits |
+| Noise Rejection | Optional noise rejection between 50 Hz and 60 Hz |
+| test | fjskfj |
+| | fjd |
+| | fjdklsfjd |
+| | fejdsklfakd |
+| | |
+
+
+
+#### Voltage Input Mode
+
+The Analog Expansion input channels can be configured for digital sensors or 0-10 V analog sensors.
+
+| Characteristics | Details |
+|------------------------|--------------------------------------------------------|
+| Digital input voltage | 0...24 V |
+| Configurable threshold | Yes (for supporting 0...10 V logic level) |
+| Analog input voltage | 0...10 V |
+| Analog input LSB value | 152.59 uV |
+| Accuracy | +/- 1% |
+| Repeatability | +/- 1% |
+| Input impedance | Min: 175 kΩ (when internal 200 kΩ resistor is enabled) |
+
+#### Current Input Mode
+
+The Analog Expansion input channels can be configured for current loop instrumentation using the 0/4-20 mA standard.
+
+| Characteristics | Details |
+|-----------------------------|---------------------------------------------|
+| Analog input current | 0...25 mA |
+| Analog input LSB value | 381.5 nA |
+| Short circuit current limit | Min: 25 mA, Max 35 mA (externally powered). |
+| Programmable current limit | 0.5 mA to 24.5 mA (loop powered) |
+| Accuracy | +/- 1% |
+| Repeatability | +/- 1% |
+
+#### RTD Input Mode
+
+The Analog Expansion input channels can be used for temperature metering with **PT100** RTDs.
+
+| Characteristics | Details |
+|-----------------|----------|
+| Input range | 0...1 MΩ |
+| Bias voltage | 2.5 V |
+
+***2 wires RTDs can be connected to any of the eight channels.***
+
+**3 Wires RTD Connection**
+
+RTD with 3 wires has generally two wires with the same color.
+
+- Connect the two wires with the same color to the - and the ICx screw terminals respectively.
+- Connect the wire with a different color to the + screw terminal.
+
+***3 wires RTD can only be measured by channels __I1__ and __I2__.***
+
+
+
+### Outputs
+
+| Characteristics | Details |
+| ----------------------------------- | ---------------------------------------- |
+| Number of channels | 8x, (2x used simultaneously recommended) |
+| Channels programmable as outputs | I1, I2, I3, I4, O1, I5, I6, O2 |
+| Type of outputs supported | Analog voltage and current |
+| DAC resolution | 13 bits |
+| Charge pump for zero voltage output | Yes |
+
+***All eight analog channels can be used as outputs but due to power dissipation limitations, it is recommended to have up to 2 channels set at output at the same time.***
+
+***At 25°C of ambient temperature, all the 8 channels set as outputs have been tested at the same time while outputting more than 24 mA at 10 V each (>0.24W per channel).***
+
+#### Voltage Output Mode
+
+This output mode lets you control voltage-driven actuators.
+
+| Characteristics | Details |
+| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
+| Analog output voltage | 0...11 V |
+| Resistive load range | 500 Ω...100 kΩ |
+| Maximum capacitive load | 2 μF |
+| Short-circuit current per channel (sourcing) | Min: 25 mA, Typ: 29 mA, Max: 32 mA (lower limit bit = 0 (default)), Min: 5.5 mA, Typ: 7 mA, Max: 9 mA (lower limit bit = 1) |
+| Short-circuit current per channel (sinking) | Min: 3.0 mA, Typ: 3.8 mA, Max: 4.5 mA |
+| Accuracy | +/- 1% |
+| Repeatability | +/- 1% |
+
+#### Current Output Mode
+
+This output mode lets you control current-driven actuators.
+
+| Characteristics | Details |
+| ------------------------------------------ | ----------------------------------------- |
+| Analog output current | 0...25 mA |
+| Maximum output voltage when sourcing 25 mA | 11.9 V ± 20% |
+| Open circuit voltage | 16.9 V ± 20% |
+| Output impedance | Min: 1.5 MΩ, Typ: 4 MΩ |
+| Accuracy | 1% in 0-10 mA range, 2% in 10-24 mA range |
+| Repeatability | 1% in 0-10 mA range, 2% in 10-24 mA range |
+
+#### PWM Output Channels
+
+The Analog Expansion has four PWM output channels **(P1...P4)**. They are software configurable and for them to work you must provide the **VPWM** pin with the desired voltage.
+
+| VPWM Voltage | Details |
+| ------------------------ | --------------------- |
+| Source voltage supported | 8...40 VDC |
+| Period | Programmable |
+| Duty-cycle | Programmable (0-100%) |
+| | |
+
+#### Status LEDs
+
+The Analog Expansion features eight user-programmable LEDs ideal for status reporting in the front panel.
+
+| Description | Value |
+|----------------|-------|
+| Number of LEDs | 8x |
+
+## Ratings
+### Recommended Operating Conditions
+
+| Description | Value |
+|-----------------------------|---------------------------|
+| Temperature Operating Range | -20...50 °C |
+| Protection degree rating | IP20 |
+| Pollution degree | 2 conforming to IEC 61010 |
+
+### Power Specification (Ambient Temperature)
+
+| Property | Min | Typ | Max | Unit |
+|-------------------------|-----|-----|------|------|
+| Supply voltage | 12 | - | 24 | V |
+| Permissible range | 9.6 | - | 28.8 | V |
+| Power consumption (12V) | 1.5 | - | - | W |
+| Power consumption (24V) | 1.8 | - | - | W |
+
+#### Additional Notes
+
+***All screw terminals marked with “-” (minus sign) are shorted together.***
+***There is no galvanic isolation between the board and its DC power supply.***
+
+## Functional Overview
+
+### Product View
+
+
+
+| Item | Feature |
+|------|------------------------------------------------------------------------------------------------------------------|
+| 3a | Power Supply Terminals 12...24 VDC |
+| 3b | P1...P4 PWM Outputs |
+| 3c | Power Status LED |
+| 3d | Analog Input/Output Terminals I1...I2 (Voltage, Current, RTD 2 wires and RTD 3 wires) |
+| 3e | Status LEDs 1...8 |
+| 3f | Port for communication and connection of auxiliary modules |
+| 3g | Analog Input/Output Terminals I3...I6 (Voltage, Current, RTD 2 wires) |
+| 3h | Analog Input/Output Terminals O1...O2 (Voltage, Current, RTD 2 wires) |
+
+### Block Diagram
+
+The following diagram explains the relation between the main components of the Opta® Analog Expansion:
+
+
+
+### Input/Output Channels
+
+The Arduino Opta® Analog Expansion features 8 channels that can be configured as inputs or outputs. When the channels are configured as inputs they can be used as digital ones with a 0-24/0-10 V range, or analog being able to measure voltage from 0 to 10 V, measure current from 0 to 25 mA or temperature leveraging the RTD mode.
+
+The channels **I1** and **I2** can be used for connecting 3-Wires RTDs. Every channel can be used also as an output, be aware that using more than two channels as an output simultaneously may overheat the device. This will depend on the ambient temperature and channel load.
+
+We have tested setting all eight channels as outputs at 25 °C outputting more than 24 mA at 10 V each during a limited timeframe.
+
+
+Warning: In case the user needs a configuration with a deviation from the suggested one, will need to validate the system performance and stability before a deployment into a production environment.
+
+
+The PWM outputs are software configurable and for them to work you must provide the **VPWM** pin with the desired voltage between 8 and 40 VDC, you can set the period and duty-cycle by software.
+
+### Expansion Port
+The expansion port can be used to daisy-chain several Opta® Expansions and additional modules. To be accessed needs to be freed up from its breakable plastic cover and the connection plug added between each device.
+
+## Device Operation
+### Getting Started - IDE
+If you want to program your Arduino Opta® Analog Expansion while offline you need to install the Arduino® Desktop IDE **[1]** and the Arduino_Opta_Blueprint using the Library Manager. To connect the Arduino Opta® to your computer, you will need a USB-C® cable.
+
+### Getting Started - Arduino Web Editor
+All Arduino® devices work out-of-the-box on the Arduino® Web Editor **[2]** by just installing a simple plugin.
+
+The Arduino® Web Editor is hosted online, therefore it will always be up-to-date with the latest features and support for all boards and devices. Follow **[3]** to start coding on the browser and upload your sketches onto your device.
+
+### Getting Started - Arduino PLC IDE
+Arduino Opta® Analog Expansion can be also programmed using the industrial-standard **_IEC 61131-3_** programming languages. Download the Arduino® PLC IDE **[4]** software, attach the Opta® Expansion through the Aux Connector and connect your Arduino Opta® to your computer using a simple USB-C® cable to start creating your own PLC industrial solutions. The PLC IDE will recognize the expansion and will expose the new available I/Os in the resources tree.
+
+### Getting Started - Arduino Cloud
+All Arduino® IoT enabled products are supported on Arduino Cloud which allows you to log, graph and analyze sensor data, trigger events, and automate your home or business.
+
+### Sample Sketches
+Sample sketches for Arduino Opta® Analog Expansions can be found in the **Arduino_Opta_Blueprint** library “Examples” in the Arduino® IDE or the “Arduino Opta® Documentation” section of Arduino® **[5]**.
+
+### Online Resources
+Now that you have gone through the basics of what you can do with the device, you can explore the endless possibilities it provides by checking exciting projects on ProjectHub **[6]**, the Arduino® Library Reference **[7]** and the online store **[8]** where you will be able to complement your Arduino Opta® product with additional extensions, sensors and actuators.
+
+## Mechanical Information
+### Product Dimensions
+
+
+***Note: Terminals can be used with both solid and stranded core wire (min: 0.5 mm2 / 20 AWG).***
+
+## Certifications
+
+### Certifications Summary
+
+| Cert | Arduino Opta® Analog Expansion (AFX00007 |
+|------------|------------------------------------------|
+| CE (EU) | EN IEC 61326-1:2021, EN IEC 61010 (LVD) |
+| CB (EU) | Yes |
+| WEEE (EU) | Yes |
+| REACH (EU) | Yes |
+| UKCA (UK) | EN IEC 61326-1:2021 |
+| FCC (US) | Yes |
+| cULus | UL 61010-2-201 |
+
+
+### Declaration of Conformity CE DoC (EU)
+We declare under our sole responsibility that the products above are in conformity with the essential requirements of the following EU Directives and therefore qualify for free movement within markets comprising the European Union (EU) and European Economic Area (EEA).
+
+### Declaration of Conformity to EU RoHS & REACH 211 01/19/2021
+
+Arduino boards are in compliance with RoHS 2 Directive 2011/65/EU of the European Parliament and RoHS 3 Directive 2015/863/EU of the Council of 4 June 2015 on the restriction of the use of certain hazardous substances in electrical and electronic equipment.
+
+| Substance | **Maximum limit (ppm)** |
+|----------------------------------------|-------------------------|
+| Lead (Pb) | 1000 |
+| Cadmium (Cd) | 100 |
+| Mercury (Hg) | 1000 |
+| Hexavalent Chromium (Cr6+) | 1000 |
+| Poly Brominated Biphenyls (PBB) | 1000 |
+| Poly Brominated Diphenyl ethers (PBDE) | 1000 |
+| Bis(2-Ethylhexyl) phthalate (DEHP) | 1000 |
+| Benzyl butyl phthalate (BBP) | 1000 |
+| Dibutyl phthalate (DBP) | 1000 |
+| Diisobutyl phthalate (DIBP) | 1000 |
+
+Exemptions: No exemptions are claimed.
+
+Arduino Boards are fully compliant with the related requirements of European Union Regulation (EC) 1907 /2006 concerning the Registration, Evaluation, Authorization and Restriction of Chemicals (REACH). We declare none of the SVHCs (https://echa.europa.eu/web/guest/candidate-list-table), the Candidate List of Substances of Very High Concern for authorization currently released by ECHA, is present in all products (and also package) in quantities totaling in a concentration equal or above 0.1%. To the best of our knowledge, we also declare that our products do not contain any of the substances listed on the "Authorization List" (Annex XIV of the REACH regulations) and Substances of Very High Concern (SVHC) in any significant amounts as specified by the Annex XVII of Candidate list published by ECHA (European Chemical Agency) 1907 /2006/EC.
+
+### Conflict Minerals Declaration
+As a global supplier of electronic and electrical components, Arduino is aware of our obligations with regards to laws and regulations regarding Conflict Minerals, specifically the Dodd-Frank Wall Street Reform and Consumer Protection Act, Section 1502. Arduino does not directly source or process conflict minerals such as Tin, Tantalum, Tungsten, or Gold. Conflict minerals are contained in our products in the form of solder, or as a component in metal alloys. As part of our reasonable due diligence Arduino has contacted component suppliers within our supply chain to verify their continued compliance with the regulations. Based on the information received thus far we declare that our products contain Conflict Minerals sourced from conflict-free areas.
+
+## FCC Caution
+Any Changes or modifications not expressly approved by the party responsible for compliance could void the user’s authority to operate the equipment.
+
+This device complies with part 15 of the FCC Rules. Operation is subject to the following two conditions:
+
+(1) This device may not cause harmful interference
+
+(2) this device must accept any interference received, including interference that may cause undesired operation.
+
+**Note:** This equipment has been tested and found to comply with the limits for a Class A digital device, pursuant to part 15 of the FCC Rules. These limits are designed to provide reasonable protection against harmful interference when the equipment is operated in a commercial environment. This equipment generates, uses, and can radiate radio frequency energy and, if not installed and used in accordance with the instruction manual, may cause harmful interference to radio communications. Operation of this equipment in a residential area is likely to cause harmful interference in which case the user will be required to correct the interference at his own expense.
+
+## Company Information
+
+| Company name | Arduino S.r.l |
+|-----------------|------------------------------------------------|
+| Company Address | Via Andrea Appiani, 25 - 20900 MONZA ( Italy ) |
+
+
+## Reference Documentation
+| **Ref** | **Link** |
+|:-------------------------------:|---------------------------------------------------------------------------------|
+| Arduino IDE (Desktop) | https://www.arduino.cc/en/Main/Software |
+| Arduino IDE (Cloud) | https://create.arduino.cc/editor |
+| Arduino Cloud - Getting started | https://docs.arduino.cc/arduino-cloud/getting-started/iot-cloud-getting-started |
+| Arduino PLC IDE | https://www.arduino.cc/en/Main/Software |
+| Arduino Opta® Documentation | https://docs.arduino.cc/hardware/opta |
+| Project Hub | https://create.arduino.cc/projecthub?by=part&part_id=11332&sort=trending |
+| Library Reference | https://www.arduino.cc/reference/en/ |
+| Online Store | https://store.arduino.cc/ |
+
+## Revision History
+
+| Date | **Revision** | **Changes** |
+| ---------- | ------------ | ------------- |
+| 25/07/2024 | 1 | First Release |
diff --git a/content/hardware/07.opta/opta-family/opta-analog-exp/downloads/AFX00007-step.zip b/content/hardware/07.opta/opta-family/opta-analog-exp/downloads/AFX00007-step.zip
new file mode 100644
index 0000000000..5746ea6076
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta-analog-exp/downloads/AFX00007-step.zip differ
diff --git a/content/hardware/07.opta/opta-family/opta-analog-exp/features.md b/content/hardware/07.opta/opta-family/opta-analog-exp/features.md
new file mode 100644
index 0000000000..7be298cf29
--- /dev/null
+++ b/content/hardware/07.opta/opta-family/opta-analog-exp/features.md
@@ -0,0 +1,47 @@
+
+
+**Arduino Opta® Analog Expansions** are designed to multiply your Opta® micro PLC capabilities with the addition of eight programmable analog inputs for connecting your digital or analog sensors, allowing you to interface with voltage, current or resistive sensors, eight analog outputs for voltage or current and four PWM outputs.
+
+Opta Analog Expansion allows professionals to scale up industrial and building automation projects while taking advantage of the Arduino ecosystem.
+
+
+
+
+
+
+
+ All the eight available channels can be configured by software as analog input or analog output. Two of those channels can get 3 wires RTD readings and the expansions have four additional PWM outputs, with a user-defined output voltage configurable from 8 to 40 VDC using the VPWM terminal.
+
+
+
+
+
+ Up to five snap-on modules managed to multiply and mix your set of I/Os with seamless detection.
+
+
+
+
+
+ Arduino Opta® Analog Expansion has a highly reliable design operating at industrial temperature ranges (-20 °C to +50 °C).
+
+
+
+
+
+ * Arduino sketch
+ * IEC-61131-3:
+ * Ladder (LD)
+ * Sequential Function Chart (SFC)
+ * Function Block Diagram (FBD)
+ * Structured Text (ST)
+ * Instruction List (IL)
+
+
+
+
+
+ Thanks to its form factor, it can be attached to a Din Rail mount system, providing quick access to all the I/O's.
+
+
+
+
diff --git a/content/hardware/07.opta/opta-family/opta-analog-exp/image.svg b/content/hardware/07.opta/opta-family/opta-analog-exp/image.svg
new file mode 100644
index 0000000000..8de9c3f327
--- /dev/null
+++ b/content/hardware/07.opta/opta-family/opta-analog-exp/image.svg
@@ -0,0 +1,564 @@
+
+
\ No newline at end of file
diff --git a/content/hardware/07.opta/opta-family/opta-analog-exp/product.md b/content/hardware/07.opta/opta-family/opta-analog-exp/product.md
new file mode 100644
index 0000000000..8e5b469707
--- /dev/null
+++ b/content/hardware/07.opta/opta-family/opta-analog-exp/product.md
@@ -0,0 +1,13 @@
+---
+title: Opta Analog Expansion
+url_shop: https://store.arduino.cc/products/opta-ext-a0602
+url_guide: /tutorials/opta-analog-exp/user-manual
+primary_button_url: /tutorials/opta/user-manual#opta-analog-expansion
+primary_button_title: User Manual
+secondary_button_url: /software/plc-ide/
+secondary_button_title: PLC IDE Guide
+core: arduino:mbed_opta
+certifications: [FCC, CE, UKCA, cULus, ENEC]
+---
+
+The **Arduino Opta® Analog Expansion** is a plug-and-play extension to the **Opta® PLC Controller** that expands its capabilities with more **inputs** with multiple functions such as digital, analog voltage, analog current or temperature and more **outputs** with analog voltage, analog current and PWM functionalities. Fully compatible with the Arduino Ecosystem.
\ No newline at end of file
diff --git a/content/hardware/07.opta/opta-family/opta-analog-exp/tech-specs.md b/content/hardware/07.opta/opta-family/opta-analog-exp/tech-specs.md
new file mode 100644
index 0000000000..3945262d27
--- /dev/null
+++ b/content/hardware/07.opta/opta-family/opta-analog-exp/tech-specs.md
@@ -0,0 +1 @@
+These are the technical specifications for Arduino Opta® Analog Expansion.
diff --git a/content/hardware/07.opta/opta-family/opta-analog-exp/tech-specs.yml b/content/hardware/07.opta/opta-family/opta-analog-exp/tech-specs.yml
new file mode 100644
index 0000000000..3e73358a21
--- /dev/null
+++ b/content/hardware/07.opta/opta-family/opta-analog-exp/tech-specs.yml
@@ -0,0 +1,32 @@
+Board:
+ SKUs:
+ Arduino Opta® Ext A0602: AFX00007
+Microcontroller:
+ ID: Renesas R7FA4M1AB3CFM ARM® Cortex®-M4
+ Cortex-M4 core: Up to 48 MHz
+Input:
+ Configurable digital / analog inputs: 8x
+ Digital operational range: 0-24 V
+ Digital configurable threshold: Yes (supports 0-10 V logic)
+ Analog resolution: 16 bit
+ Analog input voltage range: 0-10 V
+ Analog input current range: 0-25 mA
+ Analog input resistance range: 0-1 MΩ
+Output:
+ Configurable analog outputs: 8x, (2x used simultaneously max recommended)
+ DAC resolution: 13 bit
+ Analog output voltage range: 0-11 V
+ Analog output current range: 0-25 mA
+ PWM outputs: 4x
+ PWM voltage output: 8-40 V
+Power:
+ Input voltage: 12-24 VDC
+Dimensions:
+ Weight: 130 g
+ Width: 70 mm
+ Length: 89 mm
+ Height: 62 mm
+IP Protection: IP20
+Programming:
+ Arduino programming language: Via Arduino IDE, Arduino CLI, Arduino Cloud
+ IEC-61131-3: Ladder Diagram (LD), Function Block Diagram (FBD), Sequential Function Chart (SFC), Structured Text (ST), Instruction List (IL)
diff --git a/content/hardware/07.opta/opta-family/opta-analog-exp/tutorials/01.user-manual b/content/hardware/07.opta/opta-family/opta-analog-exp/tutorials/01.user-manual
new file mode 120000
index 0000000000..fb2e175bbf
--- /dev/null
+++ b/content/hardware/07.opta/opta-family/opta-analog-exp/tutorials/01.user-manual
@@ -0,0 +1 @@
+../../../../07.opta/opta-family/opta/tutorials/01.user-manual
\ No newline at end of file
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/analog-4-20-in-out.png b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/analog-4-20-in-out.png
new file mode 100644
index 0000000000..f22a47278f
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/analog-4-20-in-out.png differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/analog-4-20-inputs.png b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/analog-4-20-inputs.png
new file mode 100644
index 0000000000..21c559161c
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/analog-4-20-inputs.png differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/analog-current.png b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/analog-current.png
new file mode 100644
index 0000000000..b45f1eb071
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/analog-current.png differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/analog-voltage.png b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/analog-voltage.png
new file mode 100644
index 0000000000..9736705195
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/analog-voltage.png differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/digital-animation.gif b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/digital-animation.gif
new file mode 100644
index 0000000000..099d8abfb1
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/digital-animation.gif differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/inputs-analog.png b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/inputs-analog.png
new file mode 100644
index 0000000000..eb4916d68e
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/inputs-analog.png differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/led-ani.gif b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/led-ani.gif
new file mode 100644
index 0000000000..5f6cf02750
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/led-ani.gif differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/leds-analog.png b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/leds-analog.png
new file mode 100644
index 0000000000..70bc4de311
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/leds-analog.png differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/outputs-analog.png b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/outputs-analog.png
new file mode 100644
index 0000000000..cdda70205b
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/outputs-analog.png differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/power-expansion-2.png b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/power-expansion-2.png
new file mode 100644
index 0000000000..83081d4d97
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/power-expansion-2.png differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/pwm-out.png b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/pwm-out.png
new file mode 100644
index 0000000000..70819323f8
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/pwm-out.png differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/pwm-setup.png b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/pwm-setup.png
new file mode 100644
index 0000000000..f7308a9eec
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/pwm-setup.png differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/rtd-2wires-user.png b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/rtd-2wires-user.png
new file mode 100644
index 0000000000..dc61495828
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/rtd-2wires-user.png differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/rtd-3wires-user.png b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/rtd-3wires-user.png
new file mode 100644
index 0000000000..162fd12438
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/rtd-3wires-user.png differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/variant-analog.png b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/variant-analog.png
new file mode 100644
index 0000000000..bbc091ca6b
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/variant-analog.png differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/volt-in-a.png b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/volt-in-a.png
new file mode 100644
index 0000000000..97dc8223a6
Binary files /dev/null and b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/assets/volt-in-a.png differ
diff --git a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/content.md b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/content.md
index cc0fd003f6..b8ff413cc9 100644
--- a/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/content.md
+++ b/content/hardware/07.opta/opta-family/opta/tutorials/01.user-manual/content.md
@@ -1700,20 +1700,7 @@ To learn more about Opta™ and the Arduino IoT Cloud, check out the following r
- [Using PLC IDE With Arduino® IoT Cloud](https://docs.arduino.cc/tutorials/opta/plc-ide-cloud-support)
-## Opta Digital Expansions
-
-Arduino Opta™ Digital Expansions are designed to multiply your Opta™ micro PLC capabilities with the addition of 16 programmable inputs for connecting your industrial sensors and 8 more relays to operate your machines. Designed in partnership with leading relay manufacturer Finder®, it allows professionals to scale up industrial and building automation projects while taking advantage of the Arduino ecosystem.
-
-The Opta™ Digital Expansions come in two variants:
-
-* [The Arduino Opta® Ext D1608E (AFX00005)](https://store.arduino.cc/products/opta-ext-d1608e) with Electromechanical Relays.
-* [The Arduino Opta® Ext D1608S (AFX00006)](https://store.arduino.cc/products/opta-ext-d1608s) with Solid State Relays.
-
-The Opta Expansions can be controlled by any Opta controller variant: [Opta™ Lite](https://store.arduino.cc/products/opta-lite), [Opta™ RS485](https://store.arduino.cc/products/opta-rs485) or [Opta™ WiFi](https://store.arduino.cc/products/opta-wifi).
-
-
-
-***The Opta™ expansions firmware must be updated to the latest version to ensure proper functioning. See this [section](#update-expansion-firmware) for a guided step-by-step.***
+## Opta Expansions
### Snapping the Expansion
@@ -1723,26 +1710,9 @@ After removing the expansion port breakable plastic cover marked as AUX, from th

-### Powering Expansions
-
-The Opta™ Digital Expansions must be externally powered to work. See the power specifications in the table below:
-
-| Property | Min | Typ | Max | Unit |
-|--------------------------|------|-----|------|------|
-| Supply voltage | 12 | - | 24 | V |
-| Permissible range | 10.2 | - | 27.6 | V |
-| Power consumption (12 V) | - | - | 3 | W |
-| Power consumption (24 V) | - | - | 3 | W |
-
-In the image below there is an example of the power wiring of the expansions:
-
-
-
-***The expansions must be externally powered to be operated and detected by the Opta™ controller.***
-
### Library Installation
-To use the Opta™ Digital Expansion with your Opta™ PLC, you need to install the `Arduino_Opta_Blueprint` library. To do so in the Arduino IDE, select the **Library Manager** from the left side menu, now search for _Opta Expansions_ and click on the install button.
+To use the Opta™ Expansions with your Opta™ PLC, you need to install the `Arduino_Opta_Blueprint` library. To do so in the Arduino IDE, select the **Library Manager** from the left side menu, now search for _Opta Expansions_ and click on the install button.

@@ -1756,6 +1726,10 @@ Once installed, you will have access to a variety of sketch examples showcasing
With the library properly installed, we will update the expansion firmware to ensure proper functioning and seamless detection.
+
+
+***The expansions must be externally powered to be operated and detected by the Opta™ controller for the firmware update and normal operation. The Aux port does not provide power to the expansion.***
+
In the Arduino IDE, navigate to **File > Examples > Arduino_Opta_Blueprint > updateExpansionFw**.

@@ -1772,7 +1746,77 @@ Type `Y` in the Serial Monitor to confirm the update and wait for it to be compl
Finally, your Opta™ expansion will be updated with the latest firmware version.
-### Programmable Inputs
+### General Library Notes
+
+This section aims to clarify some recommendations for your programming experience to be as smooth as possible in your solution-developing process.
+
+When you are using the `Arduino_Opta_Blueprint` library, please take into account that `OptaController.update()` must be called cyclically to support the hot plug of new expansions. In other words, by calling the update() function cyclically, the controller will discover new expansions when they are plugged in while the controller is already running.
+
+Thanks to this function, the action of plugging in a new expansion will cause the controller to start a completely new discovery process and a new I2C address assignment.
+
+`OptaController.update()` function DOES NOT:
+* Check if an expansion has been removed and remove their objects
+* Update any data from or to the expansion
+
+
+The expansion object in the example above is defined using the `OptaController.getExpansion(i);` function, as follows:
+
+
+```arduino
+//For Digital Expansions
+for(int i = 0; i < 5; i++) { // check all the five available expansion slots
+ DigitalMechExpansion mechExp = OptaController.getExpansion(i);
+ DigitalStSolidExpansion stsolidExp = OptaController.getExpansion(i);
+}
+
+//For Analog Expansions:
+for(int i = 0; i < OptaController.getExpansionNum(); i++) { // check all the available expansion slots
+ AnalogExpansion exp = OptaController.getExpansion(i);
+}
+```
+The above method will check if there is an Ext D1608E or Ext D1608S expansion connected in the `i` index from the five admitted. If any is found in the asked index, the expansion `mechExp` or `stsolidExp` turns to true. This will ensure which expansion the read state belongs to.
+
+In the case of using analog expansions, the same method is used but checking for an Ext A0602 expansion. If any is found in the asked index, the `exp` object turns to true.
+
+The library supports the `OptaController.getExpansionNum()`. This function always returns the number of expansions discovered during the last discovery / assign I2C address process.
+
+Since the discovery process is NOT performed if an expansion is removed or powered down, the value returned by this function DOES NOT change in case of the removal of one Expansion. To know if an expansion is missing, register a callback using `setFailedCommCb(callback)` (available on all the Expansion classes).
+
+The callback will be called any time an I2C expected answer is not received by the controller, allowing the user to know that expansion is missing. No "heartbeat" function is provided to understand if an expansion is missing since having an expansion and not regularly communicating with it is not a behavior meant by design.
+
+### Opta Digital Expansions
+
+Arduino Opta™ Digital Expansions are designed to multiply your Opta™ micro PLC capabilities with the addition of 16 programmable inputs for connecting your industrial sensors and 8 more relays to operate your machines. Designed in partnership with leading relay manufacturer Finder®, it allows professionals to scale up industrial and building automation projects while taking advantage of the Arduino ecosystem.
+
+The Opta™ Digital Expansions come in two variants:
+
+* [The Arduino Opta® Ext D1608E (AFX00005)](https://store.arduino.cc/products/opta-ext-d1608e) with Electromechanical Relays.
+* [The Arduino Opta® Ext D1608S (AFX00006)](https://store.arduino.cc/products/opta-ext-d1608s) with Solid State Relays.
+
+The Opta Expansions can be controlled by any Opta controller variant: [Opta™ Lite](https://store.arduino.cc/products/opta-lite), [Opta™ RS485](https://store.arduino.cc/products/opta-rs485) or [Opta™ WiFi](https://store.arduino.cc/products/opta-wifi).
+
+
+
+***The Opta™ expansions firmware must be updated to the latest version to ensure proper functioning. See this [section](#update-expansion-firmware) for a guided step-by-step.***
+
+#### Powering Expansions
+
+The Opta™ Digital Expansions must be externally powered to work. See the power specifications in the table below:
+
+| **Property** | **Min** | **Typ** | **Max** | **Unit** |
+|:------------------------:|:-------:|:-------:|:-------:|:--------:|
+| Supply voltage | 12 | - | 24 | V |
+| Permissible range | 10.2 | - | 27.6 | V |
+| Power consumption (12 V) | - | - | 3 | W |
+| Power consumption (24 V) | - | - | 3 | W |
+
+In the image below there is an example of the power wiring of the expansions:
+
+
+
+***The expansions must be externally powered to be operated and detected by the Opta™ controller.***
+
+#### Programmable Inputs
The Opta™ Expansions have **16 analog/digital programmable inputs** accessible through terminals `I1` to `I16`.
@@ -1782,32 +1826,12 @@ Both Ext D1608E and Ext D1608S variant inputs can be used as **digital** with a

-
-
-
-
Characteristics
-
Details
-
-
-
-
-
Number of inputs
-
16x Digital/Analog inputs
-
-
-
Inputs overvoltage protection
-
yes (up to 40 V)
-
-
-
Reverse protection
-
no
-
-
-
Input impedance
-
5.85 kΩ
-
-
-
+| **Characteristics** | **Details** |
+|:-----------------------------:|:-------------------------:|
+| Number of inputs | 16x Digital/Analog inputs |
+| Inputs overvoltage protection | Yes (up to 40 V) |
+| Reverse protection | No |
+| Input impedance | 5.85 kΩ |
Analog/digital input terminals are mapped as described in the following table:
@@ -1830,34 +1854,24 @@ Analog/digital input terminals are mapped as described in the following table:
| I15 | 14 |
| I16 | 15 |
+The **reading time** of digital and analog inputs is detailed in the table below:
+
+| **Channel type** | **Number of inputs** | **Function** | **Time** | **Notes** |
+|:----------------:|:--------------------:|:------------------------------:|:--------:|:-----------------------------------------------------------------------------------------------------:|
+| Digital | All at once | `digitalRead(pin, true)` | ~580 µs | This function even if used to read a "single pin" actually updates the value of all the digital pins. |
+| Digital | All at once | `updateDigitalInputs()` | ~580 µs | This function is also included in the measure `digitalRead(0, false)` |
+| Analog | One | `getAnalogRead(channel, true)` | ~600 µs | Time does not change converting the value to physical unit (i.e. using `pinVoltage()`) |
+| Analog | All at once | `updateAnalogInputs()` | ~1.28 ms | This function is also included in the measure `getAnalogRead(0, false)` |
+
#### Digital
-
-
-
-
Characteristics
-
Details
-
-
-
-
-
Digital Input voltage
-
0...24V
-
-
-
Digital Input voltage logic level
-
VIL Max: 4 VDC. VHL Min: 5.9 VDC
-
-
-
Digital Input current
-
4.12mA at 24V | 2.05mA at 10V
-
-
-
Digital Input frequency
-
300 Hz
-
-
-
+| **Characteristics** | **Details** |
+|:---------------------------------:|:--------------------------------:|
+| Digital Input voltage | 0...24V |
+| Digital Input voltage logic level | VIL Max: 4 VDC. VHL Min: 5.9 VDC |
+| Digital Input current | 4.12mA at 24V \| 2.05mA at 10V |
+| Digital Input frequency | 300 Hz |
+| All inputs at once reading time | ~580 µs |
The state of an input terminal, configured as digital, can be read using the built-in function `digitalRead()` as shown below:
@@ -1990,25 +2004,8 @@ void loop() {
}
```
-Please take into account that `OptaController.update()` must be called cyclically to support the hot plug of new expansions. In other words, by calling the update() function cyclically, the controller will discover new expansions when they are plugged in while the controller is already running.
-
-Thanks to this function, the action of plugging in a new expansion will cause the controller to start a completely new discovery process and a new I2C address assignment.
-
-`OptaController.update()` function DOES NOT:
-* Check if an expansion has been removed and remove their objects
-* Update any data from or to the expansion
-
-The expansion object in the example above is defined using the `OptaController.getExpansion(i);` function, as follows:
-
-
-```arduino
-for(int i = 0; i < 5; i++) { // check all the five available expansion slots
- DigitalMechExpansion mechExp = OptaController.getExpansion(i);
- DigitalStSolidExpansion stsolidExp = OptaController.getExpansion(i);
-}
-```
-The above method will check if there is an Ext D1608E or Ext D1608S expansion connected in the `i` index from the five admitted. If any is found in the asked index, the expansion `mechExp` or `stsolidExp` turns to true. This will ensure which expansion the read state belongs to.
+To fully understand the example above, we recommend you to check the [General Library Notes](#general-library-notes) section.
The function `.updateDigitalInputs();` updates all the inputs with their current states to prepare them to be read.
@@ -2021,36 +2018,17 @@ LL LL LL LL LL HH LL LL LL LL LL LL LL LL LL LL

-***General note: The library supports the OptaController.getExpansionNum(). This function always returns the number of expansions discovered during the last discovery / assign I2C address process. Since the discovery process is NOT performed if an expansion is removed or powered down, the value returned by this function DOES NOT change in case of the removal of one Expansion. To know if an expansion is missing, register a callback using setFailedCommCb(cb) (available on all the Expansion classes). The callback will be called any time an I2C expected answer is not received by the controller, allowing the user to know that expansion is missing. No "heartbeat" function is provided to understand if an expansion is missing since having an expansion and not regularly communicating with it is not a behavior meant by design.***
-
#### Analog
-
-
-
-
Characteristics
-
Details
-
-
-
-
-
Analog Input voltage
-
0...24V
-
-
-
Analog Input resolution
-
14 bits
-
-
-
Analog Input LSB value
-
1.733 mV
-
-
-
Accuracy
-
+/- 5%, repeatability +/- 2%
-
-
-
+| **Characteristics** | **Details** |
+|:-------------------------------:|:-----------:|
+| Analog Input voltage | 0...24V |
+| Analog Input resolution | 14 bits |
+| Analog Input LSB value | 1.733 mV |
+| Accuracy | +/- 5% |
+| Repeatability | +/- 2% |
+| One input reading time | ~600 µs |
+| All inputs at once reading time | ~1.28 ms |
The state of an input terminal, configured as analog, can be read using the built-in function `analogRead()` as shown below:
@@ -2186,15 +2164,7 @@ void loop() {
}
```
-The expansion object in the example above is defined using the `OptaController.getExpansion(i);` function, as follows:
-
-```arduino
-for(int i = 0; i < 5; i++) { // check all the five available expansion slots
- DigitalMechExpansion mechExp = OptaController.getExpansion(i);
- DigitalStSolidExpansion stsolidExp = OptaController.getExpansion(i);
-}
-```
-The above method will check if there is an Ext D1608E or Ext D1608S expansion connected in the `i` index from the five admitted. If any is found in the asked index, the expansion `mechExp` or `stsolidExp` turns to true. This will ensure which expansion the read value belongs to.
+To fully understand the example above, we recommend you to check the [General Library Notes](#general-library-notes) section.
After the Opta™ controller is programmed with the example sketch, open the Arduino IDE Serial Monitor and you will see each input voltage as follows:
@@ -2205,7 +2175,8 @@ Expansion[0]: type DIGITAL [Mechanical], I2C address: 11

-### Outputs
+
+#### Outputs
The Opta™ Expansions have **8 relay outputs** accessible through terminals pairs `1` to `8`.
@@ -2227,161 +2198,47 @@ Relay Output terminals are mapped as described in the following table:
The **Ext D1608E (EMR)** variant features 8 electromechanical relays with the following characteristics:
-
-
-
-
Characteristics
-
Details
-
-
-
-
-
Number of outputs
-
8x Electromechanical Relays (Normally Open - SPST)
-
-
-
Max current per relay
-
6A
-
-
-
Max peak current per relay
-
10A
-
-
-
Continuous current per terminal
-
6A
-
-
-
Short-circuit protection
-
No, external fuse required
-
-
-
Relay rated voltage
-
250 VAC
-
-
-
Relay Max voltage
-
400 VAC
-
-
-
Rated load AC1
-
1500 VA
-
-
-
Rated load AC15 (230 VAC)
-
300 VA
-
-
-
Breaking capacity DC1: 24/110/220V
-
6/0.2/0.12A
-
-
-
Minimum switching load
-
500mW (12V/10mA)
-
-
-
Max output line length (unshielded)
-
100 m
-
-
-
Relay response time from state 0 to state 1
-
5 ms for relay output
-
-
-
Relay response time from state 1 to state 0
-
3 ms for relay output
-
-
-
Bounce time NO
-
1 ms
-
-
-
Bounce time NC
-
6 ms
-
-
-
Relay mechanical durability
-
10 million cycles (DC)
-
-
-
Relay electrical durability
-
60 thousand cycles with a resistive load (AC1)
-
-
-
+| **Characteristics** | **Details** |
+|:-------------------------------------------:|:--------------------------------------------------:|
+| Number of outputs | 8x Electromechanical Relays (Normally Open - SPST) |
+| Max current per relay | 6A |
+| Max peak current per relay | 10A |
+| Continuous current per terminal | 6A |
+| Short-circuit protection | No, external fuse required |
+| Relay rated voltage | 250 VAC |
+| Relay Max voltage | 400 VAC |
+| Rated load AC1 | 1500 VA |
+| Rated load AC15 (230 VAC) | 300 VA |
+| Breaking capacity DC1: 24/110/220V | 6/0.2/0.12A |
+| Minimum switching load | 500mW (12V/10mA) |
+| Max output line length (unshielded) | 100 m |
+| Relay response time from state 0 to state 1 | 5 ms for relay output |
+| Relay response time from state 1 to state 0 | 3 ms for relay output |
+| Bounce time NO | 1 ms |
+| Bounce time NC | 6 ms |
+| Relay mechanical durability | 10 million cycles (DC) |
+| Relay electrical durability | 60 thousand cycles with a resistive load (AC1) |
The **Ext D1608S (SSR)** variant features 8 solid state relays with the following characteristics:
-
-
-
-
Characteristics
-
Details
-
-
-
-
-
Number of outputs
-
8x Solid State Relays (Normally Open - SPST)
-
-
-
Max current per relay
-
2A
-
-
-
Max peak current per relay
-
50A (10 ms)
-
-
-
Continuous current per terminal
-
2A
-
-
-
Short-circuit protection
-
No, external fuse required
-
-
-
Relay rated voltage
-
24 VDC
-
-
-
Switching voltage range
-
1.5...30 VDC
-
-
-
Maximum blocking voltage
-
33 VDC
-
-
-
Rated load DC13
-
36 W
-
-
-
Minimum switching current
-
1 mA
-
-
-
Max "OFF-state" leakage current
-
0.001 mA
-
-
-
Max "OFF-state" voltage drop
-
0.4 V
-
-
-
Relay response time from state 0 to state 1
-
0.02 ms for relay output
-
-
-
Relay response time from state 1 to state 0
-
0.2 ms for relay output
-
-
-
Electrical life at rated load
-
> 10 million cycles
-
-
-
+| **Characteristics** | **Details** |
+|:-------------------------------------:|:--------------------------------------------:|
+| Number of outputs | 8x Solid State Relays (Normally Open - SPST) |
+| Max current per relay | 2A |
+| Max peak current per relay | 50A (10 ms) |
+| Continuous current per terminal | 2A |
+| Short-circuit protection | No, external fuse required |
+| Relay rated voltage | 24 VDC |
+| Switching voltage range | 1.5...30 VDC |
+| Maximum blocking voltage | 33 VDC |
+| Rated load DC13 | 36 W |
+| Minimum switching current | 1 mA |
+| Max "OFF-state" leakage current | 0.001 mA |
+| Max "OFF-state" voltage drop | 0.4 V |
+| Relay response time from state 0 to 1 | 0.02 ms for relay output |
+| Relay response time from state 1 to 0 | 0.2 ms for relay output |
+| Electrical life at rated load | > 10 million cycles |
+
The state of an output terminal, in the Ext D1608S or Ext D1608E variant, can be set using the built-in function `digitalWrite()` as shown below:
@@ -2564,15 +2421,7 @@ void loop() {
}
}
```
-The expansion object in the example above is defined using the `OptaController.getExpansion(i);` function, as follows:
-
-```arduino
-for(int i = 0; i < 5; i++) { // check all the five available expansion slots
- DigitalMechExpansion mechExp = OptaController.getExpansion(i);
- DigitalStSolidExpansion stsolidExp = OptaController.getExpansion(i);
-}
-```
-The above method will check if there is an Ext D1608E or Ext D1608S expansion connected in the `i` index from the five admitted. If any is found in the asked index, the expansion `mechExp` or `stsolidExp` turns to true. This will ensure which expansion is going to be controlled.
+To fully understand the example above, we recommend you to check the [General Library Notes](#general-library-notes) section.
First, the desired relay states need to be defined with the `digitalWrite()` function, then with the `.updateDigitalOutputs()` the states are sent to the expansion to control the relays with the defined states.
@@ -2594,6 +2443,1662 @@ You can buy and find more information about the Opta™ Digital Expansions on th
- [Buy the Opta™ Digital Ext D1608E (EMR)](https://store.arduino.cc/products/Opta-Ext-D1608E)
- [Buy the Opta™ Digital Ext D1608S (SSR)](https://store.arduino.cc/products/Opta-Ext-D1608S)
+### Opta Analog Expansions
+
+Arduino Opta® Analog Expansions are designed to multiply your Opta® micro PLC capabilities with the addition of 8x channels that can be programmed as inputs or outputs for connecting your analog voltage, current, resistive temperature sensors or analog actuators in addition to 4x dedicated PWM outputs. It allows professionals to scale up industrial and building automation projects, diversifying the type of signals managed, while taking advantage of the Arduino ecosystem.
+
+The Opta Expansions can be controlled by any Opta controller variant: [Opta™ Lite](https://store.arduino.cc/products/opta-lite), [Opta™ RS485](https://store.arduino.cc/products/opta-rs485) or [Opta™ WiFi](https://store.arduino.cc/products/opta-wifi).
+
+
+
+***The Opta™ expansions firmware must be updated to the latest version to ensure proper functioning. See this [section](#update-expansion-firmware) for a guided step-by-step procedure.***
+
+#### Powering Expansions
+
+The Opta™ Analog Expansions must be externally powered to work. See the power specifications in the table below:
+
+| **Property** | **Min** | **Typ** | **Max** | **Unit** |
+|:------------------------:|:-------:|:-------:|:-------:|:--------:|
+| Supply voltage | 12 | - | 24 | V |
+| Permissible range | 10.2 | - | 27.6 | V |
+| Power consumption (12 V) | - | - | 3 | W |
+| Power consumption (24 V) | - | - | 3 | W |
+
+In the image below there is an example of the power wiring of the expansions:
+
+
+
+***The expansions must be externally powered to be operated and detected by the Opta™ controller.***
+
+#### Programmable Inputs
+
+The Opta™ Analog Expansion has 8x analog channels, identified with a letter, `I` or `O`, between the two connection terminals: `+` for signal and `-` as GND, common to the other `-` terminals on the board.
+Each input can be used as:
+
+| **Mode** | **Specification** |
+|:------------------------------:|:-----------------:|
+| Digital input voltage | 0...24 V |
+| Analog input voltage | 0...10 V |
+| Analog input current | 0...25 mA |
+| Analog temperature input (RTD) | 0...1 MΩ |
+
+***All the analog channels of the analog expansion can be used as inputs, including `O1` and `O2`, so a total of 8x analog inputs are available to the users.***
+
+
+
+
+| **Characteristics** | **Details** |
+|:-------------------------------:|:-----------------------------------------------------:|
+| Number of channels | 8x |
+| Channels programmable as inputs | I1, I2, I3, I4, O1, I5, I6, O2 |
+| Type of inputs accepted | Digital Voltage and Analog (Voltage, Current and RTD) |
+| Inputs overvoltage protection | Yes (Up to 40 V) |
+| Antipolarity protection | No |
+| Analog Input resolution | 16 bits |
+| Noise Rejection | Optional noise rejection between 50 Hz and 60 Hz |
+
+Input terminals are mapped in the [Arduino_Opta_Blueprint](https://github.com/arduino-libraries/Arduino_Opta_Blueprint) library as described in the following table:
+
+| **Opta Analog Expansion Terminal** | **Arduino Pin Mapping** |
+|:----------------------------------:|:-----------------------:|
+| I1 | 0 or OA_CH_0 |
+| I2 | 1 or OA_CH_1 |
+| I3 | 2 or OA_CH_2 |
+| I4 | 3 or OA_CH_3 |
+| O1 | 4 or OA_CH_4 |
+| I5 | 5 or OA_CH_5 |
+| I6 | 6 or OA_CH_6 |
+| O2 | 7 or OA_CH_7 |
+
+The **reading time** of digital and analog inputs is detailed in the table below:
+
+| **Channel type** | **Number of inputs** | **Function** | **Time** | **Notes** |
+|:----------------:|:--------------------:|:------------------------:|:--------:|:-----------------------------------------------------------------------------------------------------:|
+| RTD | One | `getRtd(channel)` | ~600 µs | - |
+| Analog | One | `getAdc(channel)` | ~550 µs | Time does not change converting the value to physical unit (i.e. using `pinVoltage()`) |
+| Analog | All at once | `updateAnalogInputs()` | ~890 µs | This function is also included in the measure `getAdc(0, false)` |
+| Digital | All at once | `digitalRead(pin, true)` | ~480 µs | This function even if used to read a "single pin" actually updates the value of all the digital pins. |
+| Digital | All at once | `updateDigitalInputs()` | ~480 µs | This function is also included in the measure `digitalRead(0, false)` |
+
+
+#### Digital Input Mode
+
+The Analog Expansion input channels can be configured as digital inputs to read 0-10 V or 0-24 V digital sensors:
+
+| **Characteristics** | **Details** |
+|:-------------------------------:|:-----------------------------------------:|
+| Channels | I1, I2, I3, I4, O1, I5, I6, O2 |
+| Digital input voltage | 0...24 V |
+| Configurable threshold | Yes (for supporting 0...10 V logic level) |
+| Digital input current | 4.12 mA at 24V \| 2.05 mA at 10V |
+| Digital input frequency | 300 Hz |
+| All inputs at once reading time | ~480 µs |
+
+The state of an input terminal configured as digital can be read using the built-in function `digitalRead()` as shown below:
+
+```arduino
+state = .digitalRead();
+```
+Use the following wiring diagram as reference to test the example below:
+
+
+
+The following example will let you read all the digital inputs of every expansion connected at once, it can be found in the Opta Digital Expansions library by navigating to **File > Examples > Arduino_Opta_Blueprint > Analog > DI**:
+
+```arduino
+#include "OptaBlue.h"
+
+#define PERIODIC_UPDATE_TIME 2000
+#define DELAY_AFTER_SETUP 1000
+
+/* -------------------------------------------------------------------------- */
+void printExpansionType(ExpansionType_t t) {
+ /* -------------------------------------------------------------------------- */
+ if (t == EXPANSION_NOT_VALID) {
+ Serial.print("Unknown!");
+ } else if (t == EXPANSION_OPTA_DIGITAL_MEC) {
+ Serial.print("Opta --- DIGITAL [Mechanical] ---");
+ } else if (t == EXPANSION_OPTA_DIGITAL_STS) {
+ Serial.print("Opta --- DIGITAL [Solid State] ---");
+ } else if (t == EXPANSION_DIGITAL_INVALID) {
+ Serial.print("Opta --- DIGITAL [!!Invalid!!] ---");
+ } else if (t == EXPANSION_OPTA_ANALOG) {
+ Serial.print("~~~ Opta ANALOG ~~~");
+ } else {
+ Serial.print("Unknown!");
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void printExpansionInfo() {
+ /* -------------------------------------------------------------------------- */
+ static long int start = millis();
+
+ if (millis() - start > 5000) {
+ start = millis();
+ Serial.print("Number of expansions: ");
+ Serial.println(OptaController.getExpansionNum());
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+ Serial.print("Expansion n. ");
+ Serial.print(i);
+ Serial.print(" type ");
+ printExpansionType(OptaController.getExpansionType(i));
+ Serial.print(" I2C address ");
+ Serial.println(OptaController.getExpansionI2Caddress(i));
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* SETUP */
+/* -------------------------------------------------------------------------- */
+void setup() {
+ /* -------------------------------------------------------------------------- */
+ Serial.begin(115200);
+ delay(2000);
+ Serial.println("*** Opta Analog Digital Input example ***");
+
+ OptaController.begin();
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+
+ for (int k = 0; k < OA_AN_CHANNELS_NUM; k++) {
+ /* all channels are initialized in the same way as VOLTAGE ADC */
+ AnalogExpansion::beginChannelAsDigitalInput(OptaController, i, // the device
+ k, // the output channel you are using
+ true, // filter comparator
+ false, // invert comparator
+ true, // use simple debounce algorithm
+ OA_DI_SINK_1, // sink 120 uA
+ OA_DI_DEB_TIME_5, // ~ 42 ms
+ false, // use fix threshold
+ 8.0, // threshold at 8 V
+ 24.0); // unused in this c }
+ }
+ }
+}
+
+/* the optaAnalogTask function runs every 2000 ms it set the pwm for all the
+ * channels from with a period equal to 10 ms and a variable duty cycle from 10%
+ * to 70% */
+
+/* -------------------------------------------------------------------------- */
+void optaAnalogTask() {
+ /* -------------------------------------------------------------------------- */
+
+ static long int start = millis();
+ static bool stop_pwm = false;
+ if (millis() - start > PERIODIC_UPDATE_TIME) {
+ start = millis();
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+ AnalogExpansion exp = OptaController.getExpansion(i);
+ if (exp) {
+ for (int j = 0; j < 8; j++) {
+ int value = exp.digitalRead((uint8_t)j, true);
+ Serial.print("DI channel ");
+ Serial.print(j);
+ Serial.print(" value ");
+ Serial.println(value);
+ }
+ Serial.println();
+ }
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* LOOP */
+/* -------------------------------------------------------------------------- */
+void loop() {
+ /* -------------------------------------------------------------------------- */
+ OptaController.update();
+ optaAnalogTask();
+}
+
+```
+
+To fully understand the example above, we recommend you to check the [General Library Notes](#general-library-notes) section.
+
+The function `optaAnalogTask()` updates all the inputs with their current states and prints out the values.
+
+After the Opta™ controller is programmed with the example sketch, open the Arduino IDE Serial Monitor and you will see each input state as follows:
+
+```
+DI channel 0 value 1
+DI channel 1 value 0
+DI channel 2 value 0
+DI channel 3 value 0
+DI channel 4 value 0
+DI channel 5 value 0
+DI channel 6 value 0
+DI channel 7 value 0
+```
+
+
+#### Analog Voltage Input Mode
+
+The Analog Expansion input channels can be configured for 0-10 V analog sensors.
+
+| **Characteristics** | **Details** |
+|:-------------------------------:|:------------------------------------------------------:|
+| Channels | I1, I2, I3, I4, O1, I5, I6, O2 |
+| Analog input voltage | 0...10 V |
+| Analog Input resolution | 16 bits |
+| Analog input LSB value | 152.59 uV |
+| Accuracy | +/- 1% |
+| Repeatability | +/- 1% |
+| Input impedance | Min: 175 kΩ (when internal 200 kΩ resistor is enabled) |
+| One input reading time | ~550 µs |
+| All inputs at once reading time | ~890 µs |
+
+The raw value of an input terminal configured as analog can be read using the built-in function `analogRead()` as shown below:
+
+```arduino
+uint16_t raw_adc = .analogRead();
+```
+Also, it can be directly converted to a voltage reading using the `pinVoltage()` function as:
+
+```arduino
+float value = exp.pinVoltage();
+```
+
+Use the following wiring diagram as reference to test the example below:
+
+
+
+The following example will let you read all the analog inputs of every expansion connected at once, it can be found in the Opta Analog Expansions library by navigating to **File > Examples > Arduino_Opta_Blueprint > Analog > ADC**:
+
+```arduino
+#include "OptaBlue.h"
+
+#define PERIODIC_UPDATE_TIME 500
+#define DELAY_AFTER_SETUP 5000
+
+using namespace Opta;
+
+
+/* -------------------------------------------------------------------------- */
+void printExpansionType(ExpansionType_t t) {
+/* -------------------------------------------------------------------------- */
+ if(t == EXPANSION_NOT_VALID) {
+ Serial.print("Unknown!");
+ }
+ else if(t == EXPANSION_OPTA_DIGITAL_MEC) {
+ Serial.print("Opta --- DIGITAL [Mechanical] ---");
+ }
+ else if(t == EXPANSION_OPTA_DIGITAL_STS) {
+ Serial.print("Opta --- DIGITAL [Solid State] ---");
+ }
+ else if(t == EXPANSION_DIGITAL_INVALID) {
+ Serial.print("Opta --- DIGITAL [!!Invalid!!] ---");
+ }
+ else if(t == EXPANSION_OPTA_ANALOG) {
+ Serial.print("~~~ Opta ANALOG ~~~");
+ }
+ else {
+ Serial.print("Unknown!");
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void printExpansionInfo() {
+/* -------------------------------------------------------------------------- */
+ static long int start = millis();
+
+ if(millis() - start > 5000) {
+ start = millis();
+ Serial.print("Number of expansions: ");
+ Serial.println(OptaController.getExpansionNum());
+
+ for(int i = 0; i < OptaController.getExpansionNum(); i++) {
+ Serial.print("Expansion n. ");
+ Serial.print(i);
+ Serial.print(" type ");
+ printExpansionType(OptaController.getExpansionType(i));
+ Serial.print(" I2C address ");
+ Serial.println(OptaController.getExpansionI2Caddress(i));
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* SETUP */
+/* -------------------------------------------------------------------------- */
+void setup() {
+/* -------------------------------------------------------------------------- */
+ Serial.begin(115200);
+ delay(2000);
+
+ OptaController.begin();
+
+
+ for(int i = 0; i < OptaController.getExpansionNum(); i++) {
+
+ for(int k = 0; k < OA_AN_CHANNELS_NUM;k++){
+ /* all channels are initialized in the same way as VOLTAGE ADC */
+ AnalogExpansion::beginChannelAsAdc(OptaController, i, // the device
+ k, // the output channel you are using
+ OA_VOLTAGE_ADC, // adc type
+ true, // enable pull down
+ false, // disable rejection
+ false, // disable diagnostic
+ 0); // disable averaging
+ }
+ }
+
+}
+
+
+/* -------------------------------------------------------------------------- */
+void optaAnalogTask() {
+/* -------------------------------------------------------------------------- */
+ static long int start = millis();
+ if(millis() - start > PERIODIC_UPDATE_TIME) {
+ start = millis();
+ for(int i = 0; i < OptaController.getExpansionNum(); i++) {
+ AnalogExpansion exp = OptaController.getExpansion(i);
+
+ if(exp) {
+ Serial.println("\nAnalog Expansion n. " + String(exp.getIndex()));
+
+
+ for(int j = 0; j < OA_AN_CHANNELS_NUM; j++) {
+ Serial.print(" - ch " + String(j));
+ int value = exp.analogRead((uint8_t)j);
+ Serial.println(" -> ADC " + String(value));
+ }
+ Serial.println();
+ }
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* LOOP */
+/* -------------------------------------------------------------------------- */
+void loop() {
+/* -------------------------------------------------------------------------- */
+ OptaController.update();
+ optaAnalogTask();
+
+}
+```
+
+After the Opta™ controller is programmed with the example sketch, open the Arduino IDE Serial Monitor and you will see each input reading as follows:
+
+```
+Analog Expansion n. 0
+ - ch 0 -> ADC 0
+ - ch 1 -> ADC 0
+ - ch 2 -> ADC 0
+ - ch 3 -> ADC 0
+ - ch 4 -> ADC 0
+ - ch 5 -> ADC 25112
+ - ch 6 -> ADC 0
+ - ch 7 -> ADC 0
+```
+
+To fully understand the example above, we recommend you to check the [General Library Notes](#general-library-notes) section.
+
+The expansion channels are configured as **analog voltage inputs** using the function `beginChannelAsAdc()` alongside the following parameters:
+
+```arduino
+AnalogExpansion::beginChannelAsAdc(OptaController, // the expansion object
+ i, // the device (connected expansion index from 0 to 5)
+ k, // the output channel you are using (0 to 7)
+ OA_VOLTAGE_ADC, // adc type (voltage input)
+ true, // enable pull down
+ false, // disable rejection
+ false, // disable diagnostic
+ 0); // disable averaging
+```
+
+You can also use the simplified dedicated method using the function `beginChannelAsVoltageAdc()` as follows:
+
+```arduino
+exp.beginChannelAsVoltageAdc(); // pass the desired input as argument
+```
+The function `optaAnalogTask()` reads all the analog input raw ADC values and prints out them. If you want to show the voltage reading instead use the following function:
+
+```arduino
+//Change
+int value = exp.analogRead((uint8_t)j); // get the raw ADC reading
+//for
+float value = exp.pinVoltage((uint8_t)j); // get the ADC reading and returns it as a voltage
+```
+
+#### Analog Current Input Mode
+
+The Analog Expansion input channels can be configured for current loop instrumentation using the 0/4-20 mA standard.
+
+| **Characteristics** | **Details** |
+|:-----------------------------------------:|:-------------------------------------------:|
+| Channels | I1, I2, I3, I4, O1, I5, I6, O2 |
+| Analog input current | 0...25 mA |
+| Analog input LSB value | 381.5 nA |
+| Short circuit current limit (per channel) | Min: 25 mA, Max 35 mA (externally powered) |
+| Programmable current limit (per channel) | 0.5 mA to 24.5 mA (loop powered) |
+| Accuracy | +/- 1% |
+| Repeatability | +/- 1% |
+| One input reading time | ~550 µs |
+| All inputs at once reading time | ~890 µs |
+
+The current of an input terminal configured in current mode can be read using the built-in function `pinCurrent()` as shown below:
+
+```arduino
+float value = exp.pinCurrent();
+```
+Use the following wiring diagram as reference to test the example below:
+
+
+
+The following example will let you measure the current in all the analog inputs of every expansion connected at once.
+
+***This sketch is a __simplified version__ created for learning purposes of the one found in __File > Examples > Arduino_Opta_Blueprint > Analog > ADC__. Please check the example available at the library in case you need to know more.***
+
+Copy and paste this code on a new sketch in your Arduino IDE:
+
+```arduino
+#include "OptaBlue.h"
+
+#define PERIODIC_UPDATE_TIME 500
+#define DELAY_AFTER_SETUP 5000
+
+using namespace Opta;
+
+
+/* -------------------------------------------------------------------------- */
+void printExpansionType(ExpansionType_t t) {
+/* -------------------------------------------------------------------------- */
+ if(t == EXPANSION_NOT_VALID) {
+ Serial.print("Unknown!");
+ }
+ else if(t == EXPANSION_OPTA_DIGITAL_MEC) {
+ Serial.print("Opta --- DIGITAL [Mechanical] ---");
+ }
+ else if(t == EXPANSION_OPTA_DIGITAL_STS) {
+ Serial.print("Opta --- DIGITAL [Solid State] ---");
+ }
+ else if(t == EXPANSION_DIGITAL_INVALID) {
+ Serial.print("Opta --- DIGITAL [!!Invalid!!] ---");
+ }
+ else if(t == EXPANSION_OPTA_ANALOG) {
+ Serial.print("~~~ Opta ANALOG ~~~");
+ }
+ else {
+ Serial.print("Unknown!");
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void printExpansionInfo() {
+/* -------------------------------------------------------------------------- */
+ static long int start = millis();
+
+ if(millis() - start > 5000) {
+ start = millis();
+ Serial.print("Number of expansions: ");
+ Serial.println(OptaController.getExpansionNum());
+
+ for(int i = 0; i < OptaController.getExpansionNum(); i++) {
+ Serial.print("Expansion n. ");
+ Serial.print(i);
+ Serial.print(" type ");
+ printExpansionType(OptaController.getExpansionType(i));
+ Serial.print(" I2C address ");
+ Serial.println(OptaController.getExpansionI2Caddress(i));
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* SETUP */
+/* -------------------------------------------------------------------------- */
+void setup() {
+/* -------------------------------------------------------------------------- */
+ Serial.begin(115200);
+ delay(2000);
+
+ OptaController.begin();
+
+
+ for(int i = 0; i < OptaController.getExpansionNum(); i++) {
+
+ for(int k = 0; k < OA_AN_CHANNELS_NUM;k++){
+ /* all channels are initialized in the same way as VOLTAGE ADC */
+ AnalogExpansion::beginChannelAsAdc(OptaController, i, // the device
+ k, // the output channel you are using
+ OA_CURRENT_ADC, // adc type
+ false, // enable pull down
+ false, // disable rejection
+ false, // disable diagnostic
+ 0); // disable averaging
+ }
+ }
+
+}
+
+
+/* -------------------------------------------------------------------------- */
+void optaAnalogTask() {
+/* -------------------------------------------------------------------------- */
+ static long int start = millis();
+ if(millis() - start > PERIODIC_UPDATE_TIME) {
+ start = millis();
+ for(int i = 0; i < OptaController.getExpansionNum(); i++) {
+ AnalogExpansion exp = OptaController.getExpansion(i);
+
+ if(exp) {
+ Serial.println("\nAnalog Expansion n. " + String(exp.getIndex()));
+
+
+ for(int j = 0; j < OA_AN_CHANNELS_NUM; j++) {
+ Serial.print(" - ch " + String(j));
+ float value = exp.pinCurrent((uint8_t)j);
+ Serial.println(" -> Current " + String(value) + " mA");
+ }
+ Serial.println();
+ }
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* LOOP */
+/* -------------------------------------------------------------------------- */
+void loop() {
+/* -------------------------------------------------------------------------- */
+ OptaController.update();
+ optaAnalogTask();
+
+}
+```
+After the Opta™ controller is programmed with the example sketch, open the Arduino IDE Serial Monitor and you will see each input reading as follows:
+
+```
+Analog Expansion n. 0
+ - ch 0 -> Current 18.20 mA
+ - ch 1 -> Current 0.00 mA
+ - ch 2 -> Current 0.00 mA
+ - ch 3 -> Current 0.00 mA
+ - ch 4 -> Current 0.00 mA
+ - ch 5 -> Current 0.00 mA
+ - ch 6 -> Current 0.00 mA
+ - ch 7 -> Current 0.00 mA
+```
+
+To fully understand the example above, we recommend you to check the [General Library Notes](#general-library-notes) section.
+
+The expansion channels are configured as **analog current inputs** using the function `beginChannelAsAdc()` alongside the following parameters:
+
+```arduino
+AnalogExpansion::beginChannelAsAdc(OptaController, // the expansion object
+ i, // the device (connected expansion index from 0 to 5)
+ k, // the output channel you are using (0 to 7)
+ OA_CURRENT_ADC, // adc type (current input)
+ false, // enable pull down
+ false, // disable rejection
+ false, // disable diagnostic
+ 0); // disable averaging
+```
+
+You can also use the simplified dedicated method using the function `beginChannelAsCurrentAdc()` as follows:
+
+```arduino
+exp.beginChannelAsCurrentAdc(); // pass the desired input as argument
+```
+
+The function `optaAnalogTask()` reads all the analog input current values and prints out them.
+
+There is another approach for interfacing 4-20 mA sensors that consists of defining the channel as a **voltage DAC** and adding a **current ADC** to the same channel, connecting the sensor to the channel and measuring the current of the loop.
+
+
+
+Use the following example sketch instead:
+
+```arduino
+#include "OptaBlue.h"
+
+#define PERIODIC_UPDATE_TIME 2000
+#define DELAY_AFTER_SETUP 200
+
+#define SENSOR_CH 0 // define the sensor channel
+
+/* -------------------------------------------------------------------------- */
+void printExpansionType(ExpansionType_t t) {
+ /* -------------------------------------------------------------------------- */
+ if (t == EXPANSION_NOT_VALID) {
+ Serial.print("Unknown!");
+ } else if (t == EXPANSION_OPTA_DIGITAL_MEC) {
+ Serial.print("Opta --- DIGITAL [Mechanical] ---");
+ } else if (t == EXPANSION_OPTA_DIGITAL_STS) {
+ Serial.print("Opta --- DIGITAL [Solid State] ---");
+ } else if (t == EXPANSION_DIGITAL_INVALID) {
+ Serial.print("Opta --- DIGITAL [!!Invalid!!] ---");
+ } else if (t == EXPANSION_OPTA_ANALOG) {
+ Serial.print("~~~ Opta ANALOG ~~~");
+ } else {
+ Serial.print("Unknown!");
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void printExpansionInfo() {
+ /* -------------------------------------------------------------------------- */
+ static long int start = millis();
+
+ if (millis() - start > 5000) {
+ start = millis();
+ Serial.print("Number of expansions: ");
+ Serial.println(OptaController.getExpansionNum());
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+ Serial.print("Expansion n. ");
+ Serial.print(i);
+ Serial.print(" type ");
+ printExpansionType(OptaController.getExpansionType(i));
+ Serial.print(" I2C address ");
+ Serial.println(OptaController.getExpansionI2Caddress(i));
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* SETUP */
+/* -------------------------------------------------------------------------- */
+void setup() {
+ /* -------------------------------------------------------------------------- */
+ Serial.begin(115200);
+ delay(2000);
+
+ OptaController.begin();
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+ AnalogExpansion exp = OptaController.getExpansion(i);
+
+ if (exp) {
+ // start the channel as a voltage DAC
+ exp.beginChannelAsDac(SENSOR_CH, //channel index
+ OA_VOLTAGE_DAC, //DAC type
+ false, //limit current (set to false so it can power the sensor current loop)
+ false, //No slew rate
+ OA_SLEW_RATE_0); //Slew rate setting.
+
+ Serial.println("Setting DAC output to 11 V on expansion n. " + String(exp.getIndex()));
+ exp.pinVoltage(SENSOR_CH, 11.0, true); // set channel 0 output to 11 V (Max voltage output)
+ delay(200); // give time for the channel to be set up
+ // add a current ADC to the same channel
+ exp.addCurrentAdcOnChannel(SENSOR_CH);
+
+ }
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+void optaAnalogTask() {
+ /* -------------------------------------------------------------------------- */
+
+ static long int start = millis();
+
+ /* using this the code inside the if will run every PERIODIC_UPDATE_TIME ms
+ assuming the function is called repeatedly in the loop() function */
+
+ if (millis() - start > PERIODIC_UPDATE_TIME) {
+ start = millis();
+
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+ AnalogExpansion exp = OptaController.getExpansion(i);
+ if (exp) {
+ float value = exp.pinCurrent(SENSOR_CH);
+ Serial.println("- ch" + String(SENSOR_CH) + " -> Current " + String(abs(value)) + " mA");
+ }
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* LOOP */
+/* -------------------------------------------------------------------------- */
+void loop() {
+ /* -------------------------------------------------------------------------- */
+ OptaController.update();
+ //printExpansionInfo();
+ optaAnalogTask();
+}
+
+```
+After the Opta™ controller is programmed with the example sketch, open the Arduino IDE Serial Monitor and you will see each input reading as follows:
+
+```
+Setting DAC output to 11 V on expansion n. 0
+- ch0 -> Current 18.20 mA
+- ch0 -> Current 18.20 mA
+- ch0 -> Current 18.20 mA
+- ch0 -> Current 18.20 mA
+```
+
+The key section of the example from above is in the `setup()` function, specifically in the way we initialize the channel to be used for the measurement:
+
+```arduino
+// start the channel as a voltage DAC
+ exp.beginChannelAsDac(SENSOR_CH, //channel index
+ OA_VOLTAGE_DAC, //DAC type
+ false, //limit current (set to false so it can power the sensor current loop)
+ false, //No slew rate
+ OA_SLEW_RATE_0); //Slew rate setting.
+
+ Serial.println("Setting DAC output to 11 V on expansion n. " + String(exp.getIndex()));
+ exp.pinVoltage(SENSOR_CH, 11.0, true); // set channel 0 output to 11 V (Max voltage output)
+ delay(200); // give time for the channel to be set up
+ // add a current ADC to the same channel
+ exp.addCurrentAdcOnChannel(SENSOR_CH);
+```
+
+First, the channel is initialized as a voltage DAC with the "limit current" parameter disabled, a voltage is set in the output that will power the current loop and then a current ADC is added to the same channel, this way we can use the `pinCurrent()` function to measure the current output of the sensor.
+
+
+#### Analog RTD Input Mode
+
+The Analog Expansion input channels can be used for temperature metering with **PT100** RTDs.
+
+| **Characteristics** | **Details** |
+|:----------------------:|:------------------------------:|
+| 3 wires channels | I1, I2 |
+| 2 wires channels | I1, I2, I3, I4, O1, I5, I6, O2 |
+| Input range | 0...1 MΩ |
+| Bias voltage | 2.5 V |
+| One input reading time | ~600 µs |
+
+
+2 wires RTDs can be connected to any of the eight channels as follows:
+
+
+
+3 wires RTDs has generally two wires with the same color.
+
+- Connect the two wires with the same color to the `-` and the `ICx` screw terminals respectively.
+- Connect the wire with a different color to the `+` screw terminal.
+
+***3 wires RTD can only be measured by channels __I1__ and __I2__.***
+
+
+
+To perform measurements of an input terminal configured as RTD use the built-in function `getRtd()` as shown below:
+
+```arduino
+float value = exp.getRtd(); // this returns the resistive value measured in the input in ohms
+```
+
+For the following example a 2 wires **PT100** will be used connected to **I1**. The sketch below will let you measure the resistance and convert it to a temperature value.
+
+***This sketch is a __simplified version__ created for learning purposes of the one found in __File > Examples > Arduino_Opta_Blueprint > Analog > RTD__. Please check the example available at the library in case you need to know more.***
+
+Copy and paste this code on a new sketch in your Arduino IDE:
+
+```arduino
+#include "OptaBlue.h"
+
+#define PERIODIC_UPDATE_TIME 2000
+#define DELAY_AFTER_SETUP 1000
+
+// RTD constants
+float a = 0.0039083;
+float b = -0.0000005775;
+
+/* -------------------------------------------------------------------------- */
+void printExpansionType(ExpansionType_t t) {
+ /* -------------------------------------------------------------------------- */
+ if (t == EXPANSION_NOT_VALID) {
+ Serial.print("Unknown!");
+ } else if (t == EXPANSION_OPTA_DIGITAL_MEC) {
+ Serial.print("Opta --- DIGITAL [Mechanical] ---");
+ } else if (t == EXPANSION_OPTA_DIGITAL_STS) {
+ Serial.print("Opta --- DIGITAL [Solid State] ---");
+ } else if (t == EXPANSION_DIGITAL_INVALID) {
+ Serial.print("Opta --- DIGITAL [!!Invalid!!] ---");
+ } else if (t == EXPANSION_OPTA_ANALOG) {
+ Serial.print("~~~ Opta ANALOG ~~~");
+ } else {
+ Serial.print("Unknown!");
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void printExpansionInfo() {
+ /* -------------------------------------------------------------------------- */
+ static long int start = millis();
+
+ if (millis() - start > 5000) {
+ start = millis();
+ Serial.print("Number of expansions: ");
+ Serial.println(OptaController.getExpansionNum());
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+ Serial.print("Expansion n. ");
+ Serial.print(i);
+ Serial.print(" type ");
+ printExpansionType(OptaController.getExpansionType(i));
+ Serial.print(" I2C address ");
+ Serial.println(OptaController.getExpansionI2Caddress(i));
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* SETUP */
+/* -------------------------------------------------------------------------- */
+void setup() {
+ /* -------------------------------------------------------------------------- */
+ Serial.begin(115200);
+ delay(2000);
+ Serial.println("*** Opta Analog RTD example ***");
+
+ OptaController.begin();
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+
+ for (int k = 0; k < OA_AN_CHANNELS_NUM; k++) {
+ /* all channels are initialized in the same way as RTD */
+ AnalogExpansion::beginChannelAsRtd(OptaController, i, // the device
+ k, // the output channel you are using
+ false, // use 3 wire RTD
+ 0.8); // current used on RTD in mA
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void optaAnalogTask() {
+ /* -------------------------------------------------------------------------- */
+
+ static long int start = millis();
+ if (millis() - start > PERIODIC_UPDATE_TIME) {
+ start = millis();
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+ AnalogExpansion aexp = OptaController.getExpansion(i);
+ if (aexp) {
+ Serial.println("Expansion n. " + String(aexp.getIndex()));
+ for (int j = 0; j < 8; j++) {
+ float value = aexp.getRtd((uint8_t)j);
+ if (value != -1.00 && value < 1000000.0) { // if the channel reading is valid
+ Serial.print("ch ");
+ Serial.print(j);
+ Serial.print(" -> ");
+ Serial.print(value);
+ Serial.print(" Ω");
+ float temp = (-(1.0 / 100.0) * (50.0 * a - 10*sqrt(b * value + 25.0 * pow(a, 2.0) - 100.0 * b))) / b;
+ Serial.print(" -> ");
+ Serial.print(temp);
+ Serial.print(" C");
+ Serial.println();
+ }
+ }
+ }
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* LOOP */
+/* -------------------------------------------------------------------------- */
+void loop() {
+ /* -------------------------------------------------------------------------- */
+ OptaController.update();
+ //printExpansionInfo();
+ optaAnalogTask();
+}
+```
+
+After the Opta™ controller is programmed with the example sketch, open the Arduino IDE Serial Monitor and you will see each input reading as follows:
+
+```
+Expansion n. 0
+ch 0 -> 109.73 Ω -> 24.99 C
+```
+
+To fully understand the example above, we recommend you to check the [General Library Notes](#general-library-notes) section.
+
+The expansion channels are configured as **RTD inputs** using the function `beginChannelAsRtd` alongside the following parameters:
+
+```arduino
+AnalogExpansion::beginChannelAsRtd(OptaController, i, // the device
+ k, // the output channel you are using
+ false, // use 3 wire RTD
+ 0.8); // current used on RTD in mA
+```
+
+The current parameter in the function above will depend on your RTD type, study your sensor datasheet to find the more suitable for it, in this case, the **PT100** used recommends a **0.8 mA** current.
+
+The function `optaAnalogTask()` reads all the RTDs connected and converts their resistive value to a temperature.
+
+#### Programmable Outputs
+
+| **Characteristics** | **Details** |
+|:-----------------------------------:|:----------------------------------------:|
+| Number of channels | 8x, (2x used simultaneously recommended) |
+| Channels programmable as outputs | I1, I2, I3, I4, O1, I5, I6, O2 |
+| Type of outputs supported | Analog voltage and current |
+| DAC resolution | 13 bits |
+| Charge pump for zero voltage output | Yes |
+| Number of PWM outputs | 4x |
+
+The Opta™ Analog Expansions have **eight analog programmable outputs** accessible through terminals `I1` to `I6` and `O1` to `O2` that can be used as:
+
+| **Mode** | **Specification** |
+|:------------------------------:|:-----------------------------------------:|
+| Analog output voltage | 0...11 V |
+| Analog output current | 0...25 mA |
+
+Analog output terminals are mapped as described in the following table:
+
+| **Opta Analog Expansion Terminal** | **Arduino Pin Mapping** |
+|:----------------------------------:|:-----------------------:|
+| I1 | 0 or OA_CH_0 |
+| I2 | 1 or OA_CH_1 |
+| I3 | 2 or OA_CH_2 |
+| I4 | 3 or OA_CH_3 |
+| O1 | 4 or OA_CH_4 |
+| I5 | 5 or OA_CH_5 |
+| I6 | 6 or OA_CH_6 |
+| O2 | 7 or OA_CH_7 |
+
+
+***All available channels of the analog expansion can be used as outputs, including `I1` to `I6`, so there are 8 accessible analog outputs actually, but due to power dissipation limitations, it is recommended to have up to 2 channels set at output at the same time.***
+
+***At 25°C of ambient temperature, all the 8 channels set as outputs have been tested at the same time while outputting more than 24 mA at 10 V each (>0.24W per channel).***
+
+Also, it features **4 PWM outputs** accessible through terminals `P1` to `P4`.
+
+PWM output terminals are mapped in the [Arduino_Opta_Blueprint](https://github.com/arduino-libraries/Arduino_Opta_Blueprint) library as described in the following table:
+
+| **Opta Analog Expansion Terminal** | **Arduino Pin Mapping** |
+|:----------------------------------:|:-----------------------:|
+| P1 | 8 or OA_PWM_CH_0 |
+| P2 | 9 or OA_PWM_CH_1 |
+| P3 | 10 or OA_PWM_CH_2 |
+| P4 | 11 or OA_PWM_CH_3 |
+
+
+
+The **writing time** of analog outputs is detailed in the table below:
+
+| **Channel type** | **Number of outputs** | **Function** | **Time** | **Notes** |
+|:----------------:|:---------------------:|:--------------------------------:|:--------:|:------------------------------------------------------------------------------------------------------------:|
+| DAC | One | `setDac(channel, value, true)` | ~560 µs | |
+| DAC | All at once | `updateAnalogOutputs()` | ~960 µs | This function is also included in the function `setDac(channel, value, false)` |
+| PWM | One | `setPwm(channel, period, pulse)` | ~700 µs | In case the new setting is equal to the old one no message is sent and the function execution takes a few µs |
+
+
+#### Analog Voltage Output Mode
+
+This output mode lets you control voltage-driven actuators or communicate with other devices through analog voltages.
+
+| **Characteristics** | **Details** |
+|:--------------------------------------------:|:-----------------------------------------------------------------------------------------------------------------------------:|
+| Channels | I1, I2, I3, I4, O1, I5, I6, O2 |
+| Analog output voltage | 0...11 V |
+| Resistive load range | 500 Ω...100 kΩ |
+| Maximum capacitive load | 2 μF |
+| Short-circuit current per channel (sourcing) | Min: 25 mA, Typ: 29 mA, Max: 32 mA (lower limit bit = 0 (default)) \| Min: 5.5 mA, Typ: 7 mA, Max: 9 mA (lower limit bit = 1) |
+| Short-circuit current per channel (sinking) | Min: 3.0 mA, Typ: 3.8 mA, Max: 4.5 mA |
+| Accuracy | +/- 1% |
+| Repeatability | +/- 1% |
+| One output writing time | ~560 µs |
+| All outputs at once writing time | ~960 µs |
+
+To set a voltage in an analog output terminal use the built-in function `pinVoltage()` as shown below:
+
+```arduino
+exp.pinVoltage(ch, , true); // the first argument is to define the output channel, the second, the voltage output
+```
+You can also configure the output voltage using the `setDac()` function as follows:
+
+```arduino
+exp.setDac(ch, ); // the first argument is to define the output channel, the second, the DAC output in bits
+```
+
+The following example will let you set an output voltage on every channel at once, increasing it sequentially.
+
+***This sketch is a __simplified version__ created for learning purposes of the one found in __File > Examples > Arduino_Opta_Blueprint > Analog > DAC__. Please check the example available at the library in case you need to know more.***
+
+Copy and paste this code on a new sketch in your Arduino IDE:
+
+```arduino
+#include "OptaBlue.h"
+
+#define PERIODIC_UPDATE_TIME 5000
+#define DELAY_AFTER_SETUP 200
+
+/* -------------------------------------------------------------------------- */
+void printExpansionType(ExpansionType_t t) {
+ /* -------------------------------------------------------------------------- */
+ if (t == EXPANSION_NOT_VALID) {
+ Serial.print("Unknown!");
+ } else if (t == EXPANSION_OPTA_DIGITAL_MEC) {
+ Serial.print("Opta --- DIGITAL [Mechanical] ---");
+ } else if (t == EXPANSION_OPTA_DIGITAL_STS) {
+ Serial.print("Opta --- DIGITAL [Solid State] ---");
+ } else if (t == EXPANSION_DIGITAL_INVALID) {
+ Serial.print("Opta --- DIGITAL [!!Invalid!!] ---");
+ } else if (t == EXPANSION_OPTA_ANALOG) {
+ Serial.print("~~~ Opta ANALOG ~~~");
+ } else {
+ Serial.print("Unknown!");
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void printExpansionInfo() {
+ /* -------------------------------------------------------------------------- */
+ static long int start = millis();
+
+ if (millis() - start > 5000) {
+ start = millis();
+ Serial.print("Number of expansions: ");
+ Serial.println(OptaController.getExpansionNum());
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+ Serial.print("Expansion n. ");
+ Serial.print(i);
+ Serial.print(" type ");
+ printExpansionType(OptaController.getExpansionType(i));
+ Serial.print(" I2C address ");
+ Serial.println(OptaController.getExpansionI2Caddress(i));
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* SETUP */
+/* -------------------------------------------------------------------------- */
+void setup() {
+ /* -------------------------------------------------------------------------- */
+ Serial.begin(115200);
+ delay(2000);
+
+ OptaController.begin();
+
+ for (int device = 0; device < OptaController.getExpansionNum(); device++) {
+
+ for (int ch = 0; ch < OA_AN_CHANNELS_NUM; ch++) {
+
+ /* odd channel are configured as voltage DAC */
+ AnalogExpansion::beginChannelAsDac(OptaController,
+ device,
+ ch,
+ OA_VOLTAGE_DAC,
+ true,
+ false,
+ OA_SLEW_RATE_0);
+ }
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+void optaAnalogTask() {
+ /* -------------------------------------------------------------------------- */
+
+ static long int start = millis();
+
+ /* using this the code inside the if will run every PERIODIC_UPDATE_TIME ms
+ assuming the function is called repeatedly in the loop() function */
+
+ if (millis() - start > PERIODIC_UPDATE_TIME) {
+ start = millis();
+
+ static uint16_t dac_value = 0;
+
+ dac_value += 1000;
+ if (dac_value > 6000) {
+ /* go in falling state */
+ dac_value = 0;
+ }
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+ AnalogExpansion exp = OptaController.getExpansion(i);
+ if (exp) {
+ Serial.println("Setting dac value " + String(dac_value) + " on expansion n. " + String(exp.getIndex()));
+ for (int ch = 0; ch < OA_AN_CHANNELS_NUM; ch++) {
+ exp.setDac(ch, dac_value);
+ }
+ }
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* LOOP */
+/* -------------------------------------------------------------------------- */
+void loop() {
+ /* -------------------------------------------------------------------------- */
+ OptaController.update();
+ printExpansionInfo();
+ optaAnalogTask();
+}
+```
+
+After the Opta™ controller is programmed with the example sketch, you can measure the voltage on the expansion outputs and experience the following behavior:
+
+
+
+To fully understand the example above, we recommend you to check the [General Library Notes](#general-library-notes) section.
+
+The expansion channels are configured as **voltage output** using the function `beginChannelAsDac()` alongside the following parameters:
+
+```arduino
+ AnalogExpansion::beginChannelAsDac(OptaController, // object class
+ device, // the device
+ ch, // the output channel
+ OA_VOLTAGE_DAC, // output mode
+ true, // enable current limit
+ false, // enable slew
+ OA_SLEW_RATE_0); // set slew rate
+```
+
+The function `optaAnalogTask()` increases sequentially the `dac_value` variable to set the voltage output on the expansion channels.
+
+#### Analog Current Output Mode
+
+This output mode lets you control current-driven actuators or communicate with other devices through analog current.
+
+| **Characteristics** | **Details** |
+|:------------------------------------------:|:-----------------------------------------:|
+| Channels | I1, I2, I3, I4, O1, I5, I6, O2 |
+| Analog output current | 0...25 mA |
+| Maximum output voltage when sourcing 25 mA | 11.9 V ± 20% |
+| Open circuit voltage | 16.9 V ± 20% |
+| Output impedance | Min: 1.5 MΩ, Typ: 4 MΩ |
+| Accuracy | 1% in 0-10 mA range, 2% in 10-24 mA range |
+| Repeatability | 1% in 0-10 mA range, 2% in 10-24 mA range |
+| One output writing time | ~560 µs |
+| All outputs at once writing time | ~960 µs |
+
+To set a current in an analog output terminal use the built-in function `pinCurrent()` as shown below:
+
+```arduino
+exp.pinCurrent(ch, , true); // the first argument is to define the output channel, the second, the current output
+```
+
+The following example will let you set an output current on every channel at once, increasing it sequentially.
+
+***This sketch is a __simplified version__ created for learning purposes of the one found in __File > Examples > Arduino_Opta_Blueprint > Analog > DAC__. Please check the example available at the library in case you need to know more.***
+
+Copy and paste this code on a new sketch in your Arduino IDE:
+
+```arduino
+#include "OptaBlue.h"
+
+#define PERIODIC_UPDATE_TIME 5000
+#define DELAY_AFTER_SETUP 200
+
+/* -------------------------------------------------------------------------- */
+void printExpansionType(ExpansionType_t t) {
+ /* -------------------------------------------------------------------------- */
+ if (t == EXPANSION_NOT_VALID) {
+ Serial.print("Unknown!");
+ } else if (t == EXPANSION_OPTA_DIGITAL_MEC) {
+ Serial.print("Opta --- DIGITAL [Mechanical] ---");
+ } else if (t == EXPANSION_OPTA_DIGITAL_STS) {
+ Serial.print("Opta --- DIGITAL [Solid State] ---");
+ } else if (t == EXPANSION_DIGITAL_INVALID) {
+ Serial.print("Opta --- DIGITAL [!!Invalid!!] ---");
+ } else if (t == EXPANSION_OPTA_ANALOG) {
+ Serial.print("~~~ Opta ANALOG ~~~");
+ } else {
+ Serial.print("Unknown!");
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void printExpansionInfo() {
+ /* -------------------------------------------------------------------------- */
+ static long int start = millis();
+
+ if (millis() - start > 5000) {
+ start = millis();
+ Serial.print("Number of expansions: ");
+ Serial.println(OptaController.getExpansionNum());
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+ Serial.print("Expansion n. ");
+ Serial.print(i);
+ Serial.print(" type ");
+ printExpansionType(OptaController.getExpansionType(i));
+ Serial.print(" I2C address ");
+ Serial.println(OptaController.getExpansionI2Caddress(i));
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* SETUP */
+/* -------------------------------------------------------------------------- */
+void setup() {
+ /* -------------------------------------------------------------------------- */
+ Serial.begin(115200);
+ delay(2000);
+
+ OptaController.begin();
+
+ for (int device = 0; device < OptaController.getExpansionNum(); device++) {
+
+ for (int ch = 0; ch < OA_AN_CHANNELS_NUM; ch++) {
+
+ /* odd channel are configured as voltage DAC */
+ AnalogExpansion::beginChannelAsDac(OptaController,
+ device,
+ ch,
+ OA_CURRENT_DAC,
+ true,
+ false,
+ OA_SLEW_RATE_0);
+ }
+ }
+}
+
+
+/* -------------------------------------------------------------------------- */
+void optaAnalogTask() {
+ /* -------------------------------------------------------------------------- */
+
+ static long int start = millis();
+
+ /* using this the code inside the if will run every PERIODIC_UPDATE_TIME ms
+ assuming the function is called repeatedly in the loop() function */
+
+ if (millis() - start > PERIODIC_UPDATE_TIME) {
+ start = millis();
+
+ static uint16_t current = 0;
+
+ current += 4;
+ if (current > 20) {
+ /* reset current */
+ current = 0;
+ }
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+ AnalogExpansion exp = OptaController.getExpansion(i);
+ if (exp) {
+ Serial.println("Setting current value " + String(current) + "mA on expansion n. " + String(exp.getIndex()));
+ for (int ch = 0; ch < OA_AN_CHANNELS_NUM; ch++) {
+ exp.pinCurrent(ch, current, true);
+ }
+ }
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* LOOP */
+/* -------------------------------------------------------------------------- */
+void loop() {
+ /* -------------------------------------------------------------------------- */
+ OptaController.update();
+ printExpansionInfo();
+ optaAnalogTask();
+}
+```
+
+After the Opta™ controller is programmed with the example sketch, you can measure the current on the expansion outputs and experience the following behavior:
+
+
+
+To fully understand the example above, we recommend you to check the [General Library Notes](#general-library-notes) section.
+
+The expansion channels are configured as **current output** using the function `beginChannelAsDac()` alongside the following parameters:
+
+```arduino
+ AnalogExpansion::beginChannelAsDac(OptaController, // object class
+ device, // the device
+ ch, // the output channel
+ OA_CURRENT_DAC, // output mode
+ true, // enable current limit
+ false, // enable slew
+ OA_SLEW_RATE_0); // set slew rate
+```
+
+The function `optaAnalogTask()` increases sequentially the `current` variable to set the current output on the expansion channels.
+
+
+***Make sure to use a resistor value that makes it possible for the output to achieve the desired current. For example, if a 3 kΩ resistor is used and you want a 10 mA output, the channel must source the resistor with 30 V, which is not possible.***
+
+#### PWM Output
+
+The Analog Expansion has 4x PWM output channels **(P1...P4)**. They are software configurable and for them to work you must provide the **VPWM** pin with the desired voltage.
+
+| **VPWM Voltage** | **Details** |
+|:------------------------------:|:---------------------:|
+| Channels | P1, P2, P3, P4 |
+| Source voltage supported | 8...24 VDC + 20% |
+| Period | Programmable |
+| Duty-cycle | Programmable (0-100%) |
+| Max current draw (per channel) | 100 mA |
+| Max frequency | 10kHz |
+| One output writing time | ~700 µs |
+
+
+
+
+To configure a PWM output terminal use the built-in function `setPWM()` as shown below:
+
+```arduino
+exp.setPwm(ch, , ); // the first argument is to define the output channel, the second, the signal period and the last one, the pulse ON time of the signal.
+```
+
+The following example will let you set a **PWM** signal on channel **P1**, increasing and decreasing its duty-cycle sequentially.
+
+***This sketch is a __simplified version__ created for learning purposes of the one found in __File > Examples > Arduino_Opta_Blueprint > Analog > PWM__. Please check the example available at the library in case you need to know more.***
+
+Copy and paste this code on a new sketch in your Arduino IDE:
+
+```arduino
+#include "OptaBlue.h"
+
+
+/* -------------------------------------------------------------------------- */
+void printExpansionType(ExpansionType_t t) {
+ /* -------------------------------------------------------------------------- */
+ if (t == EXPANSION_NOT_VALID) {
+ Serial.print("Unknown!");
+ } else if (t == EXPANSION_OPTA_DIGITAL_MEC) {
+ Serial.print("Opta --- DIGITAL [Mechanical] ---");
+ } else if (t == EXPANSION_OPTA_DIGITAL_STS) {
+ Serial.print("Opta --- DIGITAL [Solid State] ---");
+ } else if (t == EXPANSION_DIGITAL_INVALID) {
+ Serial.print("Opta --- DIGITAL [!!Invalid!!] ---");
+ } else if (t == EXPANSION_OPTA_ANALOG) {
+ Serial.print("~~~ Opta ANALOG ~~~");
+ } else {
+ Serial.print("Unknown!");
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void printExpansionInfo() {
+ /* -------------------------------------------------------------------------- */
+ static long int start = millis();
+
+ if (millis() - start > 5000) {
+ start = millis();
+ Serial.print("Number of expansions: ");
+ Serial.println(OptaController.getExpansionNum());
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+ Serial.print("Expansion n. ");
+ Serial.print(i);
+ Serial.print(" type ");
+ printExpansionType(OptaController.getExpansionType(i));
+ Serial.print(" I2C address ");
+ Serial.println(OptaController.getExpansionI2Caddress(i));
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* SETUP */
+/* -------------------------------------------------------------------------- */
+void setup() {
+ /* -------------------------------------------------------------------------- */
+ Serial.begin(115200);
+ delay(2000);
+
+ OptaController.begin();
+}
+
+/* the optaAnalogTask function runs every 2000 ms it set the pwm for all the
+ * channels from with a period equal to 10 ms and a variable duty cycle from 10%
+ * to 70% */
+
+/* -------------------------------------------------------------------------- */
+void optaAnalogTask() {
+ /* -------------------------------------------------------------------------- */
+
+ static long int start = millis();
+ static bool stop_pwm = false;
+ if (millis() - start > 2000) {
+ if (Serial.available()) {
+ while (Serial.available()) {
+ Serial.read();
+ }
+ stop_pwm = !stop_pwm;
+ }
+ start = millis();
+ static uint16_t period = 10000;
+ static uint16_t pulse = 0;
+ static bool rising = 1;
+ if (rising) {
+ pulse += 1000;
+ if (pulse > 7000) {
+ rising = 0;
+ }
+ } else {
+ pulse -= 1000;
+ if (pulse <= 1000) {
+ rising = 1;
+ }
+ }
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+
+ AnalogExpansion aexp = OptaController.getExpansion(i);
+
+ if (aexp) {
+ if (stop_pwm) {
+ Serial.println("PWM stopped");
+ aexp.setPwm(OA_FIRST_PWM_CH, 0, pulse);
+ } else {
+ Serial.println("PWM started");
+ Serial.print("ON time set to: ");
+ Serial.print(pulse);
+ Serial.println(" us");
+ aexp.setPwm(OA_FIRST_PWM_CH, period, pulse);
+ }
+ }
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* LOOP */
+/* -------------------------------------------------------------------------- */
+void loop() {
+ /* -------------------------------------------------------------------------- */
+ OptaController.update();
+ //printExpansionInfo();
+ optaAnalogTask();
+}
+
+```
+
+After the Opta™ controller is programmed with the example sketch, you can measure the output signal with an oscilloscope on the expansion outputs and experience the following behavior:
+
+
+
+***The screw terminal marked as __-__ is connected to GND.***
+
+To fully understand the example above, we recommend you to check the [General Library Notes](#general-library-notes) section.
+
+The function `optaAnalogTask()` increases sequentially the `duty-cycle` variable to set the PWM output on the expansion channels and decrease it back generating a swiping output.
+
+You can use the following auxiliary functions to manage and monitor the PWM outputs:
+
+- `getPwmPeriod()`: Get the PWM period of the defined channel in us
+- `getPwmPulse()`: Get the PWM pulse duration of the defined channel in us
+- `getPwmFreqHz()`: Get the PWM frequency of the defined channel in Hz
+- `getPwmPulsePerc()`: Get the PWM pulse duty-cycle of the defined channel in %
+
+#### Expansion Status LEDs
+
+| **Characteristics** | **Details** |
+|:-------------------:|:-----------:|
+| Number of LEDs | 8x |
+
+
+
+The Opta™ Analog Expansions have **eight status LEDs** on the front panel. They are mapped in the [Arduino_Opta_Blueprint](https://github.com/arduino-libraries/Arduino_Opta_Blueprint) library as described in the following table:
+
+| **Opta Analog Expansion LED** | **Arduino Pin Mapping** |
+|:-----------------------------:|:-----------------------:|
+| LED 1 | 0 or OA_LED_1 |
+| LED 2 | 1 or OA_LED_2 |
+| LED 3 | 2 or OA_LED_3 |
+| LED 4 | 3 or OA_LED_4 |
+| LED 5 | 4 or OA_LED_5 |
+| LED 6 | 5 or OA_LED_6 |
+| LED 7 | 6 or OA_LED_7 |
+| LED 8 | 7 or OA_LED_8 |
+
+To control a status LED use the built-in function `switchLedOn()` or `switchLedOff()` as shown below:
+
+```arduino
+// Turn ON
+exp.switchLedOn(, ); // define the LED to control and set to true or false the update parameter
+
+// Turn OFF
+exp.switchLedOff(, ); // define the LED to control and set to true or false the update parameter
+```
+If the `update` parameter is set to "false", then you will be setting the desired status of the LED but it won't be applied until you call `updateLeds()` function.
+
+```arduino
+exp.switchLedOn(OA_LED_1, false); // set the desired status to the queue
+exp.updateLeds(); // apply the changes and update the current LED state
+```
+
+The following example will let you control the status LEDs sequentially, this sketch can be found in **File > Examples > Arduino_Opta_Blueprint > Analog > LED**:
+
+```arduino
+#include "OptaBlue.h"
+
+#define PERIODIC_UPDATE_TIME 2 //actually not used (it's DELAY_LED that leads the timing)
+#define DELAY_AFTER_SETUP 1000
+#define DELAY_LED 250
+
+/* -------------------------------------------------------------------------- */
+void printExpansionType(ExpansionType_t t) {
+ /* -------------------------------------------------------------------------- */
+ if (t == EXPANSION_NOT_VALID) {
+ Serial.print("Unknown!");
+ } else if (t == EXPANSION_OPTA_DIGITAL_MEC) {
+ Serial.print("Opta --- DIGITAL [Mechanical] ---");
+ } else if (t == EXPANSION_OPTA_DIGITAL_STS) {
+ Serial.print("Opta --- DIGITAL [Solid State] ---");
+ } else if (t == EXPANSION_DIGITAL_INVALID) {
+ Serial.print("Opta --- DIGITAL [!!Invalid!!] ---");
+ } else if (t == EXPANSION_OPTA_ANALOG) {
+ Serial.print("~~~ Opta ANALOG ~~~");
+ } else {
+ Serial.print("Unknown!");
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+void printExpansionInfo() {
+ /* -------------------------------------------------------------------------- */
+ static long int start = millis();
+
+ if (millis() - start > 5000) {
+ start = millis();
+ Serial.print("Number of expansions: ");
+ Serial.println(OptaController.getExpansionNum());
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+ Serial.print("Expansion n. ");
+ Serial.print(i);
+ Serial.print(" type ");
+ printExpansionType(OptaController.getExpansionType(i));
+ Serial.print(" I2C address ");
+ Serial.println(OptaController.getExpansionI2Caddress(i));
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* SETUP */
+/* -------------------------------------------------------------------------- */
+void setup() {
+ /* -------------------------------------------------------------------------- */
+ Serial.begin(115200);
+ delay(2000);
+ Serial.println("*** Opta Analog LED example ***");
+
+ OptaController.begin();
+}
+
+
+
+/* -------------------------------------------------------------------------- */
+void optaAnalogTask() {
+ /* -------------------------------------------------------------------------- */
+ static bool st = true;
+ static long int start = millis();
+
+ static const char *msg_on = "ON";
+ static const char *msg_off = "OFF";
+ static char *msg_ptr = (char *)msg_on;
+
+ if (millis() - start > PERIODIC_UPDATE_TIME) {
+ start = millis();
+
+ for (int i = 0; i < OptaController.getExpansionNum(); i++) {
+
+ AnalogExpansion exp = OptaController.getExpansion(i);
+ if (exp) {
+
+ /* exp is true only if exp is an actual
+ * AnalogExpansion and false otherwise */
+
+ for (int j = 0; j < 8; j++) {
+ if (st) {
+ msg_ptr = (char *)msg_on;
+ exp.switchLedOn((uint8_t)j, false);
+ } else {
+ msg_ptr = (char *)msg_off;
+ exp.switchLedOff((uint8_t)j, false);
+ }
+ exp.updateLeds();
+ delay(250);
+ Serial.print("switching LED ");
+ Serial.print(j);
+ Serial.print(" ");
+ Serial.println(msg_ptr);
+ }
+
+ st = !st;
+ }
+ }
+ }
+}
+
+/* -------------------------------------------------------------------------- */
+/* LOOP */
+/* -------------------------------------------------------------------------- */
+void loop() {
+ /* -------------------------------------------------------------------------- */
+ OptaController.update();
+ //printExpansionInfo();
+ optaAnalogTask();
+}
+```
+After the Opta™ controller is programmed with the example sketch, you can see the onboard LEDs blinking with a pattern and experience the following behavior:
+
+
+
+To fully understand the example above, we recommend you to check the [General Library Notes](#general-library-notes) section.
+
+The function `optaAnalogTask()` turns on sequentially the **LEDs** and turns them off again.
+
+You can buy and find more information about the Opta™ Analog Expansions on the links below:
+
+- [Opta™ Analog Expansion Product Page](https://docs.arduino.cc/hardware/opta-analog-ext)
+- [Buy the Opta™ Analog Ext A0602](https://store.arduino.cc/products/opta-ext-a0602)
+
+
## Support
If you encounter any issues or have questions while working with Opta™ devices, we provide various support resources to help you find answers and solutions.