# UNO Q — Pins, Buses & Controlling Attached Components **All physical I/O belongs to the MCU (STM32).** You control attached components by writing an Arduino sketch that owns the pin/bus. If Linux/Python needs to be involved, expose the control as a Bridge function and call it from Python (see the Bridge reference). MCU I/O is **3.3 V logic**. ## Digital pins 47 digital pins total (22 on the UNO-style header, 25 on the JMISC connector). UNO-style header mapping: | MCU pin | Arduino | Function | |---|---|---| | PB7 | D0 / RX | GPIO / UART RX | | PB6 | D1 / TX | GPIO / UART TX | | PB3 | D2 | GPIO | | PB0 | D3 | GPIO / OPAMP OUT / **PWM** | | PA12 | D4 / FDCAN1_TX | GPIO / CAN TX | | PA11 | D5 / FDCAN1_RX | GPIO / CAN RX / **PWM** | | PB1 | D6 | GPIO / **PWM** | | PB2 | D7 | GPIO | | PB4 | D8 | GPIO | | PB8 | D9 | GPIO / **PWM** | | PB9 | D10 / SS | GPIO / SPI SS / **PWM** | | PB15 | D11 / MOSI | GPIO / SPI MOSI / **PWM** | | PB14 | D12 / MISO | GPIO / SPI MISO | | PB13 | D13 / SCK | GPIO / SPI SCK | | PA4 | D14 / DAC0 | GPIO / ADC / DAC | | PA5 | D15 / DAC1 | GPIO / ADC / DAC | | PA6 | D16 | GPIO / ADC / OPAMP IN+ | | PA7 | D17 | GPIO / ADC / OPAMP IN- | | PC1 | D18 / SDA2 | GPIO / ADC / I2C SDA | | PC0 | D19 / SCL2 | GPIO / ADC / I2C SCL | | PB11 | D20 / SDA | GPIO / I2C SDA | | PB10 | D21 / SCL | GPIO / I2C SCL | Usage: ```cpp pinMode(pin, INPUT | OUTPUT | INPUT_PULLUP); state = digitalRead(pin); digitalWrite(pin, HIGH | LOW); ``` Button-reads-input, LED-follows example: `pinMode(btn, INPUT_PULLUP); if (digitalRead(btn)==LOW) digitalWrite(led,HIGH);` ## Analog input (ADC) — JANALOG connector 6 channels, **14-bit** ADC. | MCU pin | Arduino | Function | |---|---|---| | PA4 | A0 | ADC / DAC | | PA5 | A1 | ADC / DAC | | PA6 | A2 | ADC / OPAMP IN+ | | PA7 | A3 | ADC / OPAMP IN- | | PC1 | A4 | ADC / I2C SDA | | PC0 | A5 | ADC / I2C SCL | ```cpp analogReadResolution(14); // 0–16383 analogReference(AR_INTERNAL2V5); // set V_REF+ (see table) int v = analogRead(A0); ``` Voltage-reference options: `AR_INTERNAL1V5` (1.5 V), `AR_INTERNAL1V8` (1.8 V), `AR_INTERNAL2V05` (2.048 V), `AR_INTERNAL2V5` (2.5 V), `AR_EXTERNAL` (2 V…VDD, external). ## Analog output (DAC) Two true DAC outputs. | MCU pin | Arduino | |---|---| | PA4 | DAC0 | | PA5 | DAC1 | ```cpp analogWriteResolution(12); // 0–4095 analogWrite(DAC0, value); ``` (Good for generating waveforms — the docs include a 60 Hz sine via a 256-point LUT clocked with `micros()`.) ## PWM 6 PWM-capable pins: **D3, D5, D6, D9, D10, D11**. Default resolution **8-bit (0–255)**; change with `analogWriteResolution(bits)`. **PWM frequency is fixed at 500 Hz.** ```cpp analogWriteResolution(10); // 0–1023 analogWrite(D3, dutyValue); ``` ## SPI | MCU pin | Arduino | |---|---| | PB9 | SS / D10 | | PB15 | MOSI / D11 | | PB14 | MISO / D12 | | PB13 | SCK / D13 | ```cpp #include #define SS D10 void setup(){ pinMode(SS,OUTPUT); digitalWrite(SS,HIGH); SPI.begin(); } void loop(){ SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0)); digitalWrite(SS, LOW); SPI.transfer(0x35); SPI.transfer(0xFA); digitalWrite(SS, HIGH); SPI.endTransaction(); } ``` ## I2C — two buses | Bus / object | SCL | SDA | Where | |---|---|---|---| | `Wire` | D21 (PB10) | D20 (PB11) | UNO-style headers | | `Wire1` | I2C4_SCL (PD12) | I2C4_SDA (PD13) | **Qwiic** connector | ```cpp #include void setup(){ Wire.begin(); } // or Wire1.begin() for Qwiic // Wire.beginTransmission(addr); Wire.write(...); Wire.endTransmission(); ``` ### Qwiic connector Plug-and-play I²C: polarized connector, daisy-chainable, built-in pull-ups, **3.3 V only** — no breadboard/soldering. Use `Wire1`. Works directly with Arduino's **Modulino** sensor/actuator family for solder-free prototyping. ## UART (hardware serial on the header) | MCU pin | Arduino | |---|---| | PB6 | USART1_TX / D1 | | PB7 | USART1_RX / D0 | Use the **`Serial1`** object for the physical D0/D1 pins on the JDIGITAL connector: ```cpp Serial1.begin(115200); Serial1.println("Hello UNO Q"); while (Serial1.available()) { char c = Serial1.read(); /* ... */ } ``` > Note: `Serial1` here is the *header UART*. It is **not** the reserved router link — that reserved `Serial1` warning in the Bridge doc refers to the internal MPU↔MCU port; on the exposed headers `Serial1` drives D0/D1. Don't confuse the two: use `Serial1` for external UART devices, and never touch the internal router transport. ## `Serial` for debugging → App Lab console Since platform **0.55.0**, plain `Serial` prints stream to the **Arduino App Lab Console** — use it like normal: ```cpp void setup(){ Serial.begin(9600); } void loop(){ Serial.println("Hello UNO Q"); delay(1000); } ``` The legacy `Monitor` object (`#include ` → `Monitor.begin()/println()`) still works for backward compatibility, but **use `Serial` for new projects.** ## How to actually control "our node's" attached hardware — recipe 1. Identify the interface the component uses (GPIO / ADC / PWM / SPI / I2C / UART) and the matching pins above. Mind **3.3 V** levels. 2. Write the **sketch** that drives it (the standard Arduino libraries work: `Servo`, `Wire`-based sensor libs, etc.). 3. If Python/AI/networking must control or read it, wrap each action in a `Bridge.provide_safe("name", fn)` on the MCU and `Bridge.call("name", ...)` from Python (see Bridge reference). 4. For quick prototyping of sensors/actuators, reach for **Qwiic + Modulino** modules to skip wiring.