A complete Real-Time Operating System that fits in a nibble of memory!
NibbleOS is an ultra-lightweight RTOS designed for Arduino boards with limited resources. It provides professional multitasking capabilities, inter-task communication, and power management - all in a single .ino file under 4KB.
- π― Single File - No libraries to install, just copy and upload
- π Tiny Footprint - Under 4KB flash, ~200 bytes RAM
- β‘ Preemptive Multitasking - Up to 6 concurrent tasks with priorities
- π Synchronization - Semaphores and events for task coordination
- π¬ Message Passing - Inter-task communication with 8-byte messages
- π Power Management - Built-in low-power modes for battery operation
- π₯οΈ Interactive Shell - Debug and control via Serial Monitor
- π‘οΈ Watchdog Support - Automatic system recovery
- β±οΈ Real-time - 100Hz scheduler with predictable timing
- Download
NibbleOS.ino - Open in Arduino IDE
- Upload to your board (Uno, Nano, Pro Mini, etc.)
- Open Serial Monitor at 115200 baud
- Type
helpto explore!
// Your first NibbleOS task
void myTask() {
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
void setup() {
os.createTask(myTask, 500, OS_PRIORITY_NORMAL, "Blinker");
os.run(); // Start the RTOS
}Connect via Serial Monitor (115200 baud) for real-time system control:
NibbleOS v1.0
Ultra-light RTOS
Type 'help' for commands
> tasks
0: Shell [RUN] Pri:3 Last:45823
1: LED [READY] Pri:1 Last:45500
2: Monitor [READY] Pri:1 Last:40000
3: WDog [READY] Pri:3 Last:45000
> mem
Free: 1823 bytes
Uptime: 46 sec
Context switches: 1247
> led 1
OK
| Command | Description | Example |
|---|---|---|
help |
Show all commands | help |
tasks |
List all tasks with status | tasks |
mem |
Memory and system stats | mem |
led <n> |
Control built-in LED | led 1 |
adc <pin> |
Read analog pin | adc A0 |
gpio <pin> <val> |
Set digital pin | gpio 7 1 |
suspend <id> |
Suspend a task | suspend 2 |
resume <id> |
Resume a task | resume 2 |
power <0|1> |
Set power mode | power 1 |
| Board | Flash | RAM | Status |
|---|---|---|---|
| Arduino Uno/Nano | ~3.5KB (11%) | ~200B (10%) | β Excellent |
| Pro Mini | ~3.5KB (11%) | ~200B (10%) | β Excellent |
| Leonardo | ~3.5KB (12%) | ~200B (8%) | β Excellent |
| Mega 2560 | ~3.5KB (1%) | ~200B (2%) | β Excellent |
| ATtiny85 | ~3.5KB (43%) | ~200B (39%) |
// Create a task
int taskId = os.createTask(function, periodMs, priority, "name");
// Task control
os.sleepTask(milliseconds); // Sleep current task
os.suspendTask(taskId); // Suspend a task
os.resumeTask(taskId); // Resume a task// Semaphores
int sem = os.createSemaphore(initialCount, "name");
os.waitSemaphore(sem, timeoutMs);
os.signalSemaphore(sem);
// Events
int evt = os.createEvent("name");
os.waitEvent(evt, timeoutMs);
os.triggerEvent(evt);// Send message to another task
uint8_t data[] = {1, 2, 3};
os.sendMessage(taskId, msgType, data, sizeof(data));
// Receive message
uint8_t buffer[8];
uint8_t type;
int size = os.receiveMessage(&type, buffer, sizeof(buffer));int alarmEvent;
void sensorTask() {
int value = analogRead(A0);
if (value > 700) {
os.triggerEvent(alarmEvent);
}
}
void alarmTask() {
os.waitEvent(alarmEvent, 0); // Wait forever
digitalWrite(BUZZER_PIN, HIGH);
os.sleepTask(1000);
digitalWrite(BUZZER_PIN, LOW);
}
void setup() {
alarmEvent = os.createEvent("Alarm");
os.createTask(sensorTask, 100, OS_PRIORITY_HIGH, "Sensor");
os.createTask(alarmTask, 0, OS_PRIORITY_NORMAL, "Alarm");
os.run();
}int dataSem;
void producer() {
// Produce data...
os.signalSemaphore(dataSem);
}
void consumer() {
os.waitSemaphore(dataSem, 0);
// Process data...
}NibbleOS includes built-in power management:
// Enable low power mode
os.setLowPowerMode(true);
// Task automatically sleeps when idle
void efficientTask() {
// Do work...
os.sleepTask(5000); // Sleep 5 seconds
}Edit these defines in NibbleOS.ino to customize:
#define OS_MAX_TASKS 6 // Maximum concurrent tasks
#define OS_SCHEDULER_FREQ_HZ 100 // Scheduler frequency
#define OS_TASK_MAX_RUNTIME_MS 2000 // Max task runtime
#define ENABLE_WATCHDOG // Enable/disable features
#define ENABLE_MESSAGING
#define ENABLE_POWER_MANAGEMENT- Context Switch: ~50ΞΌs on 16MHz ATmega328
- Scheduler Overhead: <2% CPU @ 100Hz
- Message Passing: ~10ΞΌs per message
- Semaphore Operations: ~5ΞΌs
Contributions are welcome! Feel free to:
- Report bugs
- Suggest features
- Submit pull requests
- Share your projects
MIT License - see LICENSE file for details.
- Educational: Learn RTOS concepts with readable code
- Practical: Production-ready for small projects
- Efficient: Minimal overhead, maximum features
- Simple: One file, zero dependencies
- Task statistics collection
- Priority inheritance for semaphores
- Dynamic task creation/deletion
- Software timers
- Queue support
- ESP8266/ESP32 port
- Start Simple: Begin with basic tasks before adding synchronization
- Watch Stack: Each task uses stack space, monitor with
memcommand - Use Priorities: Critical tasks should have higher priority
- Avoid Blocking: Use events/semaphores instead of busy waiting
- Test Limits: Use shell to suspend/resume tasks during development
Made with β€οΈ for the Arduino community
β Star this project if you find it useful!