Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
ignazkevenaar committed Jul 22, 2024
1 parent 24403d2 commit 026fab4
Show file tree
Hide file tree
Showing 12 changed files with 271 additions and 146 deletions.
7 changes: 6 additions & 1 deletion docs/.vitepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,19 @@ module.exports = {
text: "Assigning Presets to Channels",
link: "/guide/presets-channels",
},
{ text: "Building and Uploading", link: "/guide/building-uploading" },
{
text: "Compiling and Uploading",
link: "/guide/compiling-uploading",
},
],
},
{
text: "Presets in depth",
items: [
{ text: "Cascading presets", link: "/guide/cascading" },
{ text: "Blinkers", link: "/guide/blinkers" },
{ text: "Sequential Blinkers", link: "/guide/sequential-blinkers" },
{ text: "US tail lights", link: "/guide/us-tail-lights" },
],
},
{
Expand Down
92 changes: 17 additions & 75 deletions docs/guide/blinkers.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,97 +12,39 @@ const PROGMEM Preset exampleBlinkPreset =
{
.modeID = BlinkL,
.mode = PresetModes::Blink,
.timeOff = 400,
.timeOn = 200
.blinkInterval = 600
};
```

This preset is applied and removed when the blink cycle swaps phase. The `timeOff` and `timeOn` properties determine how long the preset is applied and defines the blinks [duty cycle](https://en.wikipedia.org/wiki/Duty_cycle).
This preset is applied and removed when the position in the blink pattern is `1`. The `blinkInterval` property determines how long the total period of the blink lasts.

## Blinkers with a default state

Most of the time, blinking presets are defined in sets:
* A normal preset<br>
acting as the default preset that is applied when the blinking preset is in the off-phase. You can use this preset to turn off
* A blinking preset that is applied when the blink phase is in the on-state.
To define the off and on state, blinking presets are defined in sets:
* A 'normal' preset<br>
acting as the underlying state when the blinking preset is in the off-phase.
* A blinking preset that applies changes when the blink preset is in the on-state.

The following example describes a set of blinking presets alternating between half intensity and full intensity:
The following example describes a channel with a set of blinking presets alternating between half and full intensity:

```c++
const PROGMEM Preset exampleBlinkPresets[] =
{
{ .modeID = BlinkL, .intensity = 0x7777 },
{ .modeID = BlinkL, .mode = PresetModes::Blink, .intensity = 0xFFFF },
{ .modeID = BlinkL, .intensity = 127 },
{ .modeID = BlinkL, .mode = PresetModes::Blink, .intensity = 255 },
};
```

## Sequential blinkers
## Blinking patterns

When you define multiple channels with blink presets that have the same period (the total of `timeOn` and `timeOff` is equal between them), you can easily configure those channels as a squential blinking pattern.
Blink presets have a pattern that can be set to allow for more control over the blink. It also helps sync multiple blink presets.

Example:
```c++
const PROGMEM Preset presetBlinkerFirst[] =
{
{ .modeID = BlinkL, .mode = PresetModes::Blink, .timeOff = 200, .timeOn = 1000 }
};

const PROGMEM Preset presetBlinkerSecond[] =
{
{ .modeID = BlinkL, .mode = PresetModes::Blink, .timeOff = 400, .timeOn = 800 }
};

const PROGMEM Preset presetBlinkerThird[] =
{
{ .modeID = BlinkL, .mode = PresetModes::Blink, .timeOff = 600, .timeOn = 600 }
};

Channel channels[] =
{
{ COUNT_OF(presetBlinkerFirst), presetBlinkerFirst },
{ COUNT_OF(presetBlinkerSecond), presetBlinkerSecond },
{ COUNT_OF(presetBlinkerThird), presetBlinkerThird },
};
const size_t channelsCount = COUNT_OF(channels);
```

## US tail lights
...with combined brake lights and blinkers.

The way most old North-American cars use a single bulb for tail lights, brake lights and turn signals is [fascinating](https://www.youtube.com/watch?v=O1lZ9n2bxWA).
Patterns are defined as an unsigned 32-bit integer where each bit represents an on or off state.

```c++
const PROGMEM Preset USTaillightPresets[] =
{
{ .modeID = Parking, .intensity = 0x7777 },
{ .modeID = Brake },
{ .modeID = BlinkL, .intensity = 0 },
{ .modeID = BlinkL, .mode = PresetModes::Blink },
};
```
In this example, the blinking light always alternates between fully off, and fully on, regardless of if the `Brake` or `Parking` modes are applied.
The default `blinkPattern` is `0b11111111111111110000000000000000`; A half-on half-off pattern in binary notation.

### Thunderbird
The most significant bit marks the start of the timeline and the pattern moves from left to right.

In some older models, the tail lights are bit more [complicated](https://www.youtube.com/watch?v=Qwzxn9ZPW-M): The blinkers and brake lights are 'overlaid' over the parking lights.

The hard part is letting the blinker take priority over the brake lights, while still taking the state of the parking lights into consideration. The following example achieves that effect:

```c++
const PROGMEM Preset thunderbirdPresets[] =
{
{ .modeID = Brake },
{ .modeID = BlinkL, .intensity = 0 },
{ .modeID = BlinkL, .mode = PresetModes::Blink },
{ .modeID = Parking, .priorityMode = SwopModes::HTP, .intensity = 0x7777 },
};
```

At first glance, the order of the presets might be a little unconventional but here is how it works:

In the example;
* the `Brake` preset is overwritten by the first `BlinkL` preset.
* the `Parking` preset has a `HTP` priority, which only applies the preset when the calculated channel intensity up to that point is **lower** than the preset intensity;<br>
The intensity of the `Parking` preset is overlaid over the `0` intensity of the first `BlinkL` preset.

_(How to combine this example with the [sequential blinkers](#sequential-blinkers) is left as an exercise for the reader.)_
::: info KEEP IN MIND
The `blinkInterval` marks the period of the pattern. For the default pattern this means the example preset above is applied for 300ms and then not applied for another 300ms.
:::
1 change: 0 additions & 1 deletion docs/guide/building-uploading.md

This file was deleted.

44 changes: 44 additions & 0 deletions docs/guide/compiling-uploading.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Compiling and Uploading

## Compiling using Arduino CLI

It is recommended to use the Arduino CLI for compiling and uploading your sketch.

When using Arduino CLI, the sketch dependencies are managed; They are automatically downloaded and installed in in isolated folder when compiling.

Dependencies on cores and libraries are defined in `sketch.yml`.

[Read more](https://arduino.github.io/arduino-cli/latest/sketch-build-process/)

To compile using the default profile (for generic ESP8266 modules):

```shell
arduino-cli compile
```

### Uploading

First, list connected boards:

```shell
arduino-cli board list
```

Then, compile and upload after setting your desired port:

```shell
arduino-cli compile -u -p [YOUR_PORT]
```

## Using Arduino IDE 1

### Installing core

Follow these instructions to install the ESP8266 core to the Arduino IDE board manager:
https://github.com/esp8266/Arduino#installing-with-boards-manager

### Installing Libraries

Arduino IDE 1 has no way of automatically managing and installing sketch dependencies from `sketch.yml`.

Please refer to `sketch.yml` to install the correct cores and dependencies.
1 change: 1 addition & 0 deletions docs/guide/devices.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ It comes built-in with support for the following LED diver ICs:

* [NXP PCA9685](https://www.nxp.com/docs/en/data-sheet/PCA9685.pdf)
* [TI LP55231](https://www.ti.com/lit/ds/symlink/lp55231.pdf)
* [Awinic AW9523](https://doc.awinic.com/doc/202403/deffbf3b-7e7b-4ff6-8e91-fd85e2d845d5.pdf)

Example definition of devices in a config:
```cpp
Expand Down
35 changes: 3 additions & 32 deletions docs/guide/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,11 @@ Sparkplug is an Arduino sketch with interchangable configurations for each of yo

To build and upload the sketch you need either:

* [Arduino CLI](https://github.com/arduino/arduino-cli)0.28
* [Arduino CLI](https://github.com/arduino/arduino-cli)1.0
* [Arduino IDE](https://www.arduino.cc/en/software) ≥1.8.15

To upload any data to the [LittleFS](https://github.com/littlefs-project/littlefs) file system using the Arduino CLI please refer to [this section](#uploading-filesystem)

## Compiling using Arduino CLI
## Compiling

It is recommended to use the Arduino CLI for compiling and uploading your sketch.

When using Arduino CLI, the sketch dependencies are managed; They are automatically downloaded and installed in in isolated folder when compiling.

Dependencies on cores and libraries are tracked in `sketch.yml`.

[Read more](https://arduino.github.io/arduino-cli/latest/sketch-build-process/)

To compile using the default profile:

```shell
arduino-cli compile
```

## Using Arduino IDE 1

### Installing core

Follow these instructions to install the ESP8266 core to the Arduino IDE board manager:
https://github.com/esp8266/Arduino#installing-with-boards-manager

### Installing Libraries

* [SparkFun LP55231 LED Driver Breakout Arduino Library
](https://github.com/sparkfun/SparkFun_LP55231_Arduino_Library)
* [Adafruit PCA9685 PWM Servo Driver Library](https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library)
* [WebSocket Server and Client for Arduino](https://github.com/Links2004/arduinoWebSockets)
* [PrintCharArray](https://github.com/RobTillaart/PrintCharArray)

Refer to `sketch.yml` to install the correct library version tested with the sketch.
To install dependencies, compile and upload Sparkplug to your microcontroller, see [Compiling and Uploading](/guide/compiling-uploading)
12 changes: 6 additions & 6 deletions docs/guide/modes.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ Modes are defined in your config. Sparkplug does not come with a default set of
```c++
enum ModeIDs
{
DaytimeRunningLights,
Parking,
LowBeams,
HighBeams,
BlinkL,
BlinkR,
DaytimeRunning,
Parking,
LowBeams,
HighBeams,
BlinkL,
BlinkR,
};

const size_t modesCount = BlinkR + 1;
Expand Down
6 changes: 3 additions & 3 deletions docs/guide/presets-channels.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ The following example defines a single channel with two basic presets:
```c++{9}
const PROGMEM Preset presetsHeadlightLeft[] =
{
{ .modeID = LowBeams, .intensity = 32 },
{ .modeID = HighBeams, .intensity = 128 },
{ .modeID = LowBeams, .intensity = 32 },
{ .modeID = HighBeams, .intensity = 128 },
};
Channel channels[] =
{
{ COUNT_OF(presetsHeadlightLeft), presetsHeadlightLeft }
{ COUNT_OF(presetsHeadlightLeft), presetsHeadlightLeft }
};
const size_t channelsCount = COUNT_OF(channels);
```
Expand Down
20 changes: 9 additions & 11 deletions docs/guide/presets.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,27 @@ The most basic presets contain a valid [`modeID`](#modes) and an `intensity` as
```c++
const PROGMEM Preset examplePreset =
{
.modeID = HighBeams,
.intensity = 255
.modeID = HighBeams,
.intensity = 255
};
```
_If you omit the `intensity` property, it will be treated as full intensity._
_Omitting the `intensity` property will default to full intensity._

By default, presets make channels 'act' like incandescent bulbs; when a preset is applied, the channel fades in to the desired `intensity`, and fades out slower when the preset is no longer applied.
By default, presets simulate incandescent bulbs; channels fade in to the desired `intensity`, and fade out slower when the preset is no longer applied.

If you want to emulate LED-based modern vehicle lighting you can set those fade times to different values:

```c++{4,5}
const PROGMEM Preset exampleLEDPreset =
{
.modeID = DaytimeRunningLights,
.fadeSpeedRising = 0,
.fadeSpeedFalling = 0,
.modeID = DaytimeRunningLights,
.fadeSpeedRising = 0,
.fadeSpeedFalling = 0,
};
```

In most real-world applications, a single vehicle light fixture can serve more than one purpose, so it is likely that a channel has multiple presets defined for each desired state of the bulb. Presets are cascading; they can take or give precedence over other presets.

This allows you to define intricate lighting that takes priority over other modes when needed, but not interfere with other modes when that is not desirable. (e.g. [US tail lights](#us-tail-lights) where the blinker takes priority over the parking lights and brake light)
This allows you to define intricate lighting that takes priority over other modes when needed, but not interfere with other modes when that is not desirable. (e.g. US tail lights, where the blinkers take priority over the parking and brake lights)

Presets also support basic blinking.

[Cascading in-depth](#cascading-in-depth)
Presets also support [Blinking](/guide/blinkers) and [Cascading](/guide/cascading) to allow presets to overtake presets with lower priority in different ways.
41 changes: 41 additions & 0 deletions docs/guide/sequential-blinkers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Sequential Blinkers

When you define multiple channels with blink presets that have the same `blinkInterval`, you can easily configure those channels as sequential by setting different blinking patterns.

Example:
```c++{6,15,24}
const PROGMEM Preset presetBlinkerFirst[] =
{
{
.modeID = BlinkL,
.mode = PresetModes::Blink,
.blinkPattern = 0b11111111111111111100000000000000
}
};
const PROGMEM Preset presetBlinkerSecond[] =
{
{
.modeID = BlinkL,
.mode = PresetModes::Blink,
.blinkPattern = 0b00000011111111111100000000000000
}
};
const PROGMEM Preset presetBlinkerThird[] =
{
{
.modeID = BlinkL,
.mode = PresetModes::Blink,
.blinkPattern = 0b00000000000011111100000000000000
}
};
Channel channels[] =
{
{ COUNT_OF(presetBlinkerFirst), presetBlinkerFirst },
{ COUNT_OF(presetBlinkerSecond), presetBlinkerSecond },
{ COUNT_OF(presetBlinkerThird), presetBlinkerThird },
};
const size_t channelsCount = COUNT_OF(channels);
```
40 changes: 40 additions & 0 deletions docs/guide/us-tail-lights.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# US tail lights
...with combined brake lights and blinkers.

Older North-American cars [use a single bulb](https://www.youtube.com/watch?v=O1lZ9n2bxWA) for tail lights, brake lights and turn signals.

```c++
const PROGMEM Preset USTaillightPresets[] =
{
{ .modeID = Parking, .intensity = 63 },
{ .modeID = Brake },
{ .modeID = BlinkL, .intensity = 0 },
{ .modeID = BlinkL, .mode = PresetModes::Blink },
};
```
In this example, the blinking light always alternates between fully off, and fully on, taking priority over the `Brake` and `Parking` presets.

## Thunderbirds

In some models, the tail lights are bit more [complicated](https://www.youtube.com/watch?v=Qwzxn9ZPW-M): The blinkers and brake lights are 'overlaid' over the parking lights.

The hard part is letting the blinker take priority over the brake lights, while still taking the state of the parking lights into consideration. The following example achieves that effect:

```c++{4,6}
const PROGMEM Preset thunderbirdPresets[] =
{
{ .modeID = Brake },
{ .modeID = BlinkL, .intensity = 0 },
{ .modeID = BlinkL, .mode = PresetModes::Blink },
{ .modeID = Parking, .priorityMode = SwopModes::HTP, .intensity = 63 },
};
```

At first glance, the order of the presets might be a little unconventional but here is how it works:

In the example;
* the `Brake` preset is cancelled by the first `BlinkL` preset.
* the `Parking` preset has a `HTP` priority, which only applies the preset when the calculated channel intensity up to that point is **lower** than the preset intensity;<br>
The intensity of the `Parking` preset is overlaid over the `0` intensity of the first `BlinkL` preset.

_(How to combine this example with the [sequential blinkers](/guide/sequential-blinkers) is left as an exercise for the reader.)_
Loading

0 comments on commit 026fab4

Please sign in to comment.