Skip to content

argeorun/BACnet-Arduino-Library

Repository files navigation

BACnet for Arduino

A professional Arduino library for BACnet MS/TP protocol with automatic board detection and memory optimization

  1. OVERVIEW

BACnet for Arduino is a complete Arduino library that brings BACnet MS/TP protocol to your Arduino projects. Featuring automatic board detection, proportional memory scaling, and focused single-object examples, this library makes it easy to create BACnet-compatible devices on Arduino hardware ranging from Uno (2KB RAM) to ESP32 (520KB RAM).

1A. Key Features

  • Automatic Board Detection - Detects Arduino board and configures memory usage automatically
  • Proportional Memory Scaling - Larger boards get more buffers and features automatically
  • Progressive Enhancement - More RAM = more BACnet objects and features enabled
  • Single-Object Examples - Each example focuses on ONE object type with ALL its features
  • Arduino Library Manager - Standard installation via Library Manager
  • Multi-Board Support - Uno, Mega, Due, Zero, ESP32, STM32, and more
  • Educational - Clear, well-documented examples for learning BACnet

1B. Supported BACnet Objects

Object Type Tier 1 (Uno) Tier 2 (Mega) Tier 3 (Due) Tier 4 (ESP32)
Binary Value (BV)
Analog Value (AV)
Binary Output (BO)
Analog Input (AI)
Multi-State Value (MSV)
Calendar
Schedule
Trend Log

1C. Board Tier System

Tier 1 (2KB RAM) - Arduino Uno, Nano

  • Basic BV and AV objects only
  • MAX_APDU: 128 bytes
  • Perfect for simple devices

Tier 2 (8KB RAM) - Arduino Mega 2560

  • All I/O objects (BO, AI, MSV)
  • COV notifications
  • Priority arrays
  • MAX_APDU: 512 bytes

Tier 3 (32KB RAM) - Arduino Due, Zero

  • Scheduling objects (Calendar, Schedule)
  • Trend logging
  • Intrinsic reporting
  • MAX_APDU: 1476 bytes

Tier 4 (64KB+ RAM) - ESP32, STM32

  • Full BACnet feature set
  • Secure Connect (future)
  • Complex multi-object systems
  1. EXAMPLE SKETCHES

The library includes 50+ examples organized by object type and complexity:

2A. Basic Examples (Tier 1 - All Boards)

  • MinimalDevice - Bare minimum BACnet device
  • DeviceDiscovery - Who-Is/I-Am demo

2B. Binary Value Examples (Tier 1)

  • BV_LED_Control - Control LED via BACnet
  • BV_DigitalInput - Read button state
  • BV_WithCOV - COV notifications (Tier 2+)

2C. Analog Value Examples (Tier 1)

  • AV_Temperature - Read LM35 temperature sensor
  • AV_ADC_Reading - Generic ADC input
  • AV_WithCOV - COV notifications (Tier 2+)

2D. Binary Output Examples (Tier 2 - Mega+)

  • BO_Relay_Control - Control relay with priority
  • BO_Multiple - Multiple relays

2E. Analog Input Examples (Tier 2 - Mega+)

  • AI_TempHumidity - DHT22 sensor
  • AI_Multiple - Multiple sensors

2F. Advanced Examples (Tier 3 - Due+)

  • Calendar_Simple - Calendar object
  • Schedule_Simple - Schedule object
  • TrendLog_Simple - Data logging

Each example includes:

  • Complete circuit diagram
  • Wiring instructions
  • Expected RAM/Flash usage
  • YABE testing guide
  1. QUICK START

3A. Installation

Option 1: Arduino Library Manager (Recommended)

  1. Open Arduino IDE
  2. Go to Sketch → Include Library → Manage Libraries
  3. Search for "BACnet for Arduino"
  4. Click Install

Option 2: Manual Installation

  1. Download the library ZIP from GitHub
  2. In Arduino IDE: Sketch → Include Library → Add .ZIP Library
  3. Select the downloaded ZIP file

3B. Your First BACnet Device (5 Minutes)

#include <BACnetArduino.h>

// Create device with MAC address 123
BACnetDevice device(123);

// Create Binary Value object (LED)
BACnetBinaryValue led(0, "LED", 13);  // Object ID 0, name "LED", pin 13

void setup() {
    Serial.begin(38400);
    device.begin();  // Displays board tier and configuration
    device.addObject(&led);
    Serial.println("BACnet Device Ready!");
}

void loop() {
    device.process();  // Handle BACnet communications
}

Upload this to your Arduino Uno with an RS-485 shield, and you'll have a BACnet device discoverable on the network!

3C. Library Structure

BACnet-for-Arduino/
├── library.properties           # Library metadata
├── keywords.txt                 # Syntax highlighting
├── LICENSE                      # MIT License (Arduino wrapper)
├── NOTICE.txt                   # Attribution to bacnet-stack
├── README.md                    # This file
│
├── src/                        # Library source code
│   ├── BACnetArduino.h         # Main library header (include this)
│   ├── BACnetDevice.h/cpp      # Device object class
│   ├── BACnetBinaryValue.h/cpp # Binary Value object
│   ├── BACnetAnalogValue.h/cpp # Analog Value object
│   ├── BACnetConfig.h          # Auto board detection
│   ├── hardware/               # Hardware abstraction
│   │   ├── BACnetRS485.h/cpp
│   │   ├── BACnetADC.h/cpp
│   │   └── BACnetTimer.h/cpp
│   └── bacnet/                 # BACnet protocol stack (original)
│
└── examples/                   # 50+ example sketches
    ├── 01.Basic/
    │   ├── MinimalDevice/
    │   └── DeviceDiscovery/
    ├── 02.BinaryValue/
    │   ├── BV_LED_Control/
    │   ├── BV_WithCOV/
    │   └── ...
    ├── 03.AnalogValue/
    ├── 04.BinaryOutput/
    ├── 05.AnalogInput/
    └── ...
  1. HARDWARE REQUIREMENTS

4A. RS-485 Transceiver Module

BACnet MS/TP uses RS-485 for communication. You'll need an RS-485 transceiver:

Recommended Modules:

  • DFRobot DFR0259 RS-485 Shield (Arduino Uno/Mega) - DE/RE control
  • Generic MAX485 module (any Arduino board) - DE/RE control
  • MAX3485, SN65HVD72 (industrial grade) - DE/RE control
  • Auto-direction RS-485 modules (UART-to-RS485 converters) - No DE/RE needed
  • SP3485, MAX13487E (auto direction) - No DE/RE needed

Typical Wiring (MAX485 with DE/RE control):

MAX485          Arduino
  VCC    →      5V
  GND    →      GND
  DI     →      TX (Serial1 TX on Mega/Due)
  RO     →      RX (Serial1 RX on Mega/Due)
  DE+RE  →      D2 (or any digital pin)
  A      →      RS-485 Bus A
  B      →      RS-485 Bus B

Wiring (Auto-Direction RS-485 modules - No DE/RE):

RS-485 Module   Arduino
  VCC    →      5V
  GND    →      GND
  TXD    →      TX (Serial1 TX on Mega/Due)
  RXD    →      RX (Serial1 RX on Mega/Due)
  A      →      RS-485 Bus A
  B      →      RS-485 Bus B

Note: Some RS-485 modules have automatic direction control and don't need DE/RE pins. Set BACNET_RS485_ENABLE_PIN to -1 for these modules.

4B. Supported Arduino Boards

Board RAM Tier Status
Arduino Uno 2KB 1 ✅ Tested
Arduino Nano 2KB 1 ✅ Compatible
Arduino Mega 2560 8KB 2 ✅ Tested
Arduino Due 96KB 3 ✅ Compatible
Arduino Zero 32KB 3 ✅ Compatible
ESP32 520KB 4 ✅ Compatible
STM32F4 128KB 4 ✅ Compatible
  1. CONFIGURATION

5A. RS-485 Port Selection

// In your sketch, before including BACnetArduino.h:
#define BACNET_RS485_PORT Serial1  // For Mega/Due (default)
// OR
#define BACNET_RS485_PORT Serial   // For Uno (uses main serial)

// RS-485 transceiver control pin (optional)
#define BACNET_RS485_ENABLE_PIN 2  // DE/RE control pin
// OR
#define BACNET_RS485_ENABLE_PIN -1 // No DE/RE control (auto direction modules)

#include <BACnetArduino.h>

5B. BACnet Device Configuration

BACnetDevice device(
    123,              // MAC address (0-127)
    260123,           // Device Instance ID (0-4194303)
    38400             // Baud rate (9600, 19200, 38400, 76800)
);

5C. Automatic Board Detection

The library automatically detects your board and configures memory limits:

void setup() {
    Serial.begin(38400);
    device.begin();  // Prints detected configuration
    // Output example:
    // === BACnet Configuration ===
    // Board: Arduino Uno
    // RAM: 2 KB
    // Tier: 1
    // MAX_APDU: 128
    // MAX_TSM: 3
    // Enabled Object Types:
    //   - Binary Value (BV)
    //   - Analog Value (AV)
}
  1. TESTING WITH YABE

YABE (Yet Another BACnet Explorer) is the recommended tool for testing:

  1. Connect RS-485 bus to your PC (USB-RS485 adapter)
  2. Launch YABE and add MS/TP device
  3. Configure COM port and baud rate (38400)
  4. Discover devices - your Arduino appears
  5. Read/Write object properties
  6. Subscribe to COV notifications (Tier 2+)

6A. Expected Results

Device: 260123 (Arduino BACnet Device)
  Object: Binary Value 0 (LED)
    Present_Value: INACTIVE
    Description: "LED on pin 13"
    Status_Flags: [0,0,0,0]

Write ACTIVE to Present_Value → LED turns ON!

  1. TROUBLESHOOTING

7A. "Binary Output not defined" Error

Problem: Trying to use Tier 2+ objects on Arduino Uno Solution: Use Arduino Mega or higher, or stick to BV/AV objects

7B. Device Not Discovered by YABE

Check:

  • RS-485 wiring correct (A-A, B-B)
  • Baud rate matches (default 38400)
  • MAC address unique on network
  • RS-485 transceiver powered
  • DE/RE pin configured correctly (or set to -1 for auto-direction modules)
  • For auto-direction modules: ensure module supports half-duplex RS-485

7C. Compilation Errors

Solution: Ensure you have latest Arduino IDE (1.8.19+) and EEPROM library installed

7D. Out of Memory

Problem: Sketch too large for board
Solution:

  • Use smaller example for your board tier
  • Reduce number of objects
  • Upgrade to board with more RAM
  1. API REFERENCE

8A. BACnetDevice Class

BACnetDevice(uint8_t mac_address, 
             uint32_t device_instance = 260001,
             uint32_t baud_rate = 38400);

void begin();                    // Initialize device
void process();                  // Process BACnet messages (call in loop)
void addObject(BACnetObject* obj); // Register object
void setDeviceName(const char* name);
void setLocation(const char* location);

8B. BACnetBinaryValue Class

BACnetBinaryValue(uint32_t instance,
                  const char* name,
                  uint8_t pin = -1);

void setValue(bool value);       // Set Present_Value
bool getValue();                 // Get Present_Value
void setPin(uint8_t pin);       // Associate with digital pin
void enableCOV();               // Enable COV notifications (Tier 2+)

8C. BACnetAnalogValue Class

BACnetAnalogValue(uint32_t instance,
                  const char* name,
                  BACNET_ENGINEERING_UNITS units = UNITS_DEGREES_CELSIUS);

void setValue(float value);      // Set Present_Value
float getValue();                // Get Present_Value
void setPin(int pin);           // Associate with ADC pin
void setUnits(BACNET_ENGINEERING_UNITS units);
void setMinValue(float min);
void setMaxValue(float max);
void enableCOV(float increment); // COV with increment (Tier 2+)
  1. DEPENDENCIES

Built-in Arduino Libraries (no installation needed):

  • Arduino.h
  • EEPROM.h
  • HardwareSerial (Serial ports)

External Libraries: None

  1. LICENSING

This library uses a dual-license structure:

10A. Arduino Wrapper Code - MIT License

All Arduino-specific code (C++ classes, examples, hardware abstraction) is licensed under MIT License:

  • src/BACnetArduino.h/cpp
  • src/BACnetDevice.h/cpp
  • src/BACnet*.h/cpp (object classes)
  • src/hardware/ (all files)
  • examples/ (all sketches)
  • Documentation files

Why MIT? Maximum compatibility with Arduino ecosystem and ease of use in both open-source and commercial projects.

10B. BACnet Protocol Stack - GPL v2+ with Linking Exception

The src/bacnet/ directory contains the original BACnet Protocol Stack with original copyright and licensing preserved:

  • Copyright: Steve Karg and contributors
  • License: GPL v2 or later with linking exception
  • Effect: You can use this library in proprietary projects thanks to the linking exception

See LICENSE and NOTICE.txt files for complete details.

  1. ACKNOWLEDGMENTS

This library is inspired by and built upon the excellent BACnet Protocol Stack project.

Original BACnet Stack:

The BACnet Protocol Stack represents years of dedicated work by talented developers to create a robust, standards-compliant BACnet implementation. This Arduino library provides a modern wrapper to make that excellent work accessible to Arduino developers, while properly crediting the original authors.

Thank you to Steve Karg and all contributors for creating and maintaining this comprehensive BACnet implementation!

  1. ADDITIONAL RESOURCES
  1. CONTRIBUTING

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch
  3. Test on physical hardware
  • Submit pull request with description
  1. SUPPORT
  • Issues: Report bugs on GitHub Issues
  • Discussions: Ask questions on GitHub Discussions
  • Email: [your.email@example.com]
  1. ROADMAP

15A. Version 1.0 (Current)

  • Arduino Uno through ESP32 support
  • Automatic board detection
  • BV, AV objects (all boards)
  • BO, AI, MSV objects (Tier 2+)
  • 50+ example sketches

15B. Version 1.1 (Planned)

  • Calendar and Schedule objects (Tier 3)
  • Trend Log object (Tier 3)
  • BACnet/IP support (ESP32, W5500 shield)
  • Web configuration interface (ESP32)

15C. Version 2.0 (Future)

  • BACnet Secure Connect (Tier 4)
  • MQTT bridge functionality
  • More object types (Accumulator, Loop, etc.)

Version: 1.0.0
Last Updated: November 26, 2025
Status: Production Ready
License: MIT (wrapper) + GPL v2+ with linking exception (stack)
Author: [Your Name]
Inspired by: BACnet Protocol Stack by Steve Karg

About

"Professional Arduino library for BACnet MS/TP protocol"

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages