PicoLC Arduino Library
Arduino library for PicoLC hardware
Loading...
Searching...
No Matches
PicoLC Arduino Library

PicoLC is an Arduino library for the PicoLC controller, a compact RP2040/RP2350-based control board designed for 12 V and 24 V automation projects.

The library provides a logical, scan-based interface for:

  • Four protected field inputs
  • Four configurable field outputs
  • Output pairing
  • Status indicators and board buttons
  • IEC-style timers
  • RS-485 communication
  • Nonvolatile user storage
  • Board-level diagnostics

PicoLC uses the Earle Philhower Arduino-Pico core and is not intended to support other Arduino cores.

Status

This library is under active development.

The public API may change while the hardware and library are being validated. Storage and paired-output support are still being finalized.

Requirements

  • PicoLC hardware
  • Raspberry Pi Pico, Pico W, Pico 2, or Pico 2 W as supported by the PicoLC board
  • Arduino IDE or Arduino CLI
  • Earle Philhower Arduino-Pico core

Installation

Install the Earle Philhower Arduino-Pico core, then install this library into your Arduino libraries directory.

For local development, place or link the repository at:

Documents/Arduino/libraries/PicoLC

Restart the Arduino IDE after adding or updating the library.

Basic Usage

#include <PicoLC.h>
PicoLC plc;
void setup() {
plc.begin();
plc.Y0.outputMode(OutputMode::HighSide);
// Physical outputs remain disabled until explicitly enabled.
}
void loop() {
// Begin a new PicoLC scan.
plc.update();
// Mirror logical input X0 to logical output Y0.
plc.Y0.write(plc.X0.read());
}
Main interface to PicoLC hardware and shared runtime services.
Definition PicoLCClass.h:25
PicoLCOutput Y0
Hardware outputs Y0 through Y3.
Definition PicoLCClass.h:42
PicoLCInput X0
Hardware inputs X0 through X3.
Definition PicoLCClass.h:45
void update()
Advances PicoLC by one application scan.
Definition PicoLC.cpp:121
void enableOutputs()
Enables physical output-driver operation.
Definition PicoLC.cpp:179
void begin()
Initializes PicoLC hardware and child objects.
Definition PicoLC.cpp:85
bool read() const
Returns the current filtered logical input state.
void outputMode(OutputMode mode)
Sets the electrical drive mode.
bool write(bool state)
Applies a logical command to the output.

Scan Model

Call plc.update() once at the beginning of each loop() iteration.

update():

  • Captures one shared millisecond timestamp for the scan
  • Increments the scan counter
  • Samples and filters inputs and buttons
  • Updates edge-detection state
  • Advances output and LED pulse, blink, and PWM behavior
  • Applies configured logical output behavior to the board

Timed API components use the timestamp captured by the most recent plc.update(). This keeps timers, filters, pulses, and blink patterns consistent within one application scan.

Logical and Physical States

The public API works with logical states.

bool inputActive = plc.X0.read();
plc.Y0.write(inputActive);

Electrical output behavior is configured separately:

plc.Y0.outputMode(OutputMode::HighSide);
plc.Y1.outputMode(OutputMode::LowSide);
plc.Y2.outputMode(OutputMode::PushPull);

Physical output drive is globally controlled through:

void disableOutputs()
Disables all physical output-driver channels.
Definition PicoLC.cpp:183

Disabling physical outputs preserves logical output states. Output indicator LEDs continue to display the states that would otherwise be sent to the physical outputs.

Inputs

PicoLC inputs expose filtered logical state and edge detection:

plc.X0.filterMillis(20);
bool active = plc.X0.read();
if (plc.X0.rising()) {
// Logical false-to-true transition
}
if (plc.X0.falling()) {
// Logical true-to-false transition
}
if (plc.X0.changed()) {
// Any logical transition
}
void filterMillis(uint32_t ms)
Sets the required input stability time.
bool changed() const
Reports any logical input transition.
bool falling() const
Reports a true-to-false logical transition.
bool rising() const
Reports a false-to-true logical transition.

Filtering and inversion are applied before logical state changes and edge detection.

Edge results remain valid until the next plc.update().

Outputs

Each output has an electrical mode, a pattern mode, and a linear PWM duty value.

plc.Y0.outputMode(OutputMode::HighSide);
plc.Y0.patternMode(PatternMode::Steady);
plc.Y0.duty(1000);
plc.Y0.write(true);
void patternMode(PatternMode mode)
Sets the timed behavior applied to the output.
uint16_t duty(uint16_t duty)
Sets the linear PWM duty.

The output duty range is:

0 = 0%
500 = 50%
1000 = 100%

Output Patterns

plc.Y0.patternMode(PatternMode::Steady);

Applies the logical state continuously.

plc.Y1.patternMode(PatternMode::Pulse);
plc.Y1.pulseLength(1000);
plc.Y1.write(true);
void pulseLength(uint32_t ms)
Sets the Pulse-mode duration.

Starts or restarts a fixed-duration pulse. Writing false stops the pulse at the next update() cycle.

plc.Y2.patternMode(PatternMode::Blink);
plc.Y2.blinkPeriod(1000);
plc.Y2.blinkOnTime(200);
plc.Y2.write(true);
void blinkOnTime(uint32_t ms)
Sets the active time within each Blink-mode cycle.
void blinkPeriod(uint32_t ms)
Sets the complete Blink-mode cycle period.

Starts a repeating blink pattern in the on phase. Writing false stops blinking at the next update() cycle.

LEDs

Board LEDs use the same steady, pulse, and blink pattern modes as outputs.

plc.StatusLED.patternMode(PatternMode::Blink);
plc.StatusLED.write(true);
PicoLCLED StatusLED
Board indicator LEDs.
Definition PicoLCClass.h:51
void blinkOnTime(uint32_t ms)
Sets the active time within each Blink-mode cycle.
Definition PicoLCLED.cpp:82
void brightness(uint16_t brightness)
Sets the perceived LED brightness.
Definition PicoLCLED.cpp:85
void blinkPeriod(uint32_t ms)
Sets the complete Blink-mode cycle period.
Definition PicoLCLED.cpp:80
void patternMode(PatternMode mode)
Sets the timed behavior applied to the LED.
Definition PicoLCLED.cpp:10
bool write(bool state)
Applies a logical command to the LED.
Definition PicoLCLED.cpp:62

LED brightness uses a user-facing range of 0 through 100. The library converts this to a nonlinear PWM value to provide more natural perceived brightness changes.

A brightness of zero does not change the logical LED state or configured pattern.

Buttons

Board buttons expose the same filtered logical-state and edge-detection interface as field inputs:

plc.BootButton.filterMillis(20);
if (plc.BootButton.rising()) {
}
bool rising() const
Reports a logical button press transition.
void filterMillis(uint32_t ms)
Sets the required button-state stability time.
void toggle()
Toggles the LED state or active pulse.
Definition PicoLCLED.cpp:70

read() returns true when the button is logically pressed.

Timers

PicoLC timers provide standard IEC-style TON, TOF, and TP behavior using the shared PicoLC scan timebase.

PicoLCTimer onDelay(plc, TimerMode::TON, 2000);
IEC-style timer using the shared PicoLC scan timebase.
Definition PicoLCTimer.h:18

The compact form performs write(input) followed by read():

plc.Y0.write(onDelay.update(plc.X0.read()));

The operations may also be called separately:

onDelay.write(plc.X0.read());
bool output = onDelay.read();

Additional timer state is available through:

onDelay.running();
onDelay.elapsed();
onDelay.remaining();
onDelay.presetMillis();
onDelay.reset();

Timers should normally be serviced once per PicoLC scan.

RS-485 Serial

plc.Serial provides an Arduino Stream-compatible interface to the PicoLC RS-485 port.

void setup() {
plc.begin();
plc.Serial.begin(19200);
}
void loop() {
plc.update();
if (plc.Serial.available()) {
int value = plc.Serial.read();
plc.Serial.write(static_cast<uint8_t>(value));
}
}
PicoLCSerial Serial
RS-485 serial interface.
Definition PicoLCClass.h:57
void begin(uint32_t baud, uint16_t config=SERIAL_8N1)
Initializes the RS-485 UART and transceiver-control pins.
size_t write(uint8_t byte) override
Transmits one byte over RS-485.
int available() override
Returns the number of received bytes available to read.
int read() override
Reads the next received byte.

The current implementation is blocking. A write call returns after transmission is complete and the RS-485 transceiver has returned to receive mode.

plc.Serial is separate from the Arduino USB Serial interface.

Board Diagnostics

Output enable state

bool enabled = plc.outputsEnabled();
bool outputsEnabled() const
Reports whether physical outputs are globally enabled.
Definition PicoLC.cpp:187

Output-driver fault

if (plc.outputFault()) {
}
bool outputFault() const
Reports the current output-driver fault indication.
Definition PicoLC.cpp:191

Output-driver reset

void resetOutputDriver()
Resets the hardware output driver.
Definition PicoLC.cpp:195

Supply voltage

float volts = plc.supplyVoltage();
float supplyVoltage() const
Measures the PicoLC supply voltage.
Definition PicoLC.cpp:199

supplyVoltage() samples the board VIN sense circuit when called and is independent of plc.update().

Examples

The library includes progressive examples covering:

  1. Basic input and output
  2. Input filtering
  3. Input edge detection
  4. Output patterns
  5. LED patterns
  6. TON timer
  7. TOF timer
  8. TP timer
  9. Global output enable
  10. Output fault monitoring

Open them through the Arduino IDE under:

File > Examples > PicoLC

Repository Layout

PicoLC/
├── examples/
├── src/
│ ├── PicoLC.h
│ ├── PicoLCClass.h
│ ├── PicoLCInput.h
│ ├── PicoLCOutput.h
│ ├── PicoLCLED.h
│ ├── PicoLCButton.h
│ ├── PicoLCTimer.h
│ ├── PicoLCSerial.h
│ └── ...
├── library.properties
├── LICENSE
└── README.md

Hardware Notes

PicoLC is designed around fixed board resources and the Earle Philhower RP2040/RP2350 Arduino core.

Some hardware resources are shared:

  • Outputs Y0 and Y1 are on the same RP2 PWM slice and share a PWM frequency
  • Outputs Y2 and Y3 also share a PWM frequency.
  • Individual outputs retain independent PWM duty values
  • Output pairs may impose additional shared configuration requirements
  • Physical outputs remain disabled until explicitly enabled

License

Released under MIT license. See LICENSE file.

Project

Project website: picolc.com