initial commit

master
skybldev 3 years ago
commit 55298a05bf

@ -0,0 +1 @@
Control an LED strip with an Arduino through a serial connection.

@ -0,0 +1,40 @@
const tps = 47;
const fade_ms = 500; // ms
const current_vals = [10, 100, 45];
const target_vals = [255, 255, 0];
var fade_increments = [0, 0, 0];
var fade_ticks = Math.ceil(fade_ms / tps); // 32
var val_iterator = 0;
var tick_iterator = 0;
console.log(`fade_ticks: ${fade_ticks}`);
while (val_iterator < 3) {
fade_increments[val_iterator] = -((current_vals[val_iterator] - target_vals[val_iterator]) / fade_ticks);
val_iterator++;
}
val_iterator = 0;
console.log(`increments: ${fade_increments}`);
while (tick_iterator < fade_ticks) {
while (val_iterator < 3) {
current_vals[val_iterator] += fade_increments[val_iterator];
val_iterator++;
}
val_iterator = 0;
console.log(current_vals.map((val) => Math.round(val)));
tick_iterator++;
}

@ -0,0 +1,23 @@
const ticks_per_second = 47;
const current_color = [10, 100, 45];
const target_color = [255, 255, 0];
const how_long_fade_is = 1500; // ms
var how_many_ticks_it_takes = Math.floor(how_long_fade_is / ticks_per_second); // 32
var percent_amount = 1;
var tick_inc = 0;
while (tick_inc < how_many_ticks_it_takes) {
let color_out = [];
for (let j = 0; j < 3; j++) {
color_out.push((current_color[j] * percent_amount) + (target_color[j] * (1 - percent_amount)));
}
console.log(`${tick_inc}: ${color_out}`);
tick_inc++;
percent_amount -= (1 / how_many_ticks_it_takes);
}

@ -0,0 +1,48 @@
#define TPS 47
#define FADE_MS 500
#include <iostream>
#include <cmath>
using namespace std;
float current_vals[] = {10, 100, 45};
int target_vals[] = {255, 255, 0};
float fade_increments[] = {0.0, 0.0, 0.0};
int fade_ticks = ceil(FADE_MS / (float) TPS);
int val_iterator = 0;
int tick_iterator = 0;
int main() {
cout << "fade_ticks: " << fade_ticks << endl;
while (val_iterator < 3) {
fade_increments[val_iterator] = -((current_vals[val_iterator] - target_vals[val_iterator]) / (float) fade_ticks);
val_iterator++;
}
val_iterator = 0;
cout << "increments: " << fade_increments[0] << ", " << fade_increments[1] << ", " << fade_increments[2] << endl;
while (tick_iterator < fade_ticks) {
while (val_iterator < 3) {
current_vals[val_iterator] += fade_increments[val_iterator];
val_iterator++;
}
val_iterator = 0;
cout << tick_iterator << ": " << round(current_vals[0]) << ", " << round(current_vals[1]) << ", " << round(current_vals[2]) << endl;
tick_iterator++;
}
return 0;
}

@ -0,0 +1,88 @@
#include <iostream>
using namespace std;
void callback(char command, char arg, int parsed_number) {
cout << "command: " << command << " | ";
cout << "arg: " << arg << " | ";
cout << "parsed_number: " << parsed_number << " | ";
cout << endl;
}
int parse_string(char input[]) {
char current_char = input[0];
char command = ' ';
char arg = ' ';
char current_number_string[4] = {' ', ' ', ' ', '\0'};
int line_position = 0;
int total_position = 0;
int current_number_len = 0;
int parsed_number = 0;
while (current_char != '\0') {
if (line_position == 0) {
switch (current_char) {
case 'f':
case 't':
case 'b':
command = current_char;
break;
default:
cout << "invalid command. " << endl;
return 1;
}
} else {
switch (current_char) {
case '0' ... '9':
if (current_number_len < 4) {
current_number_len++;
current_number_string[current_number_len - 1] = current_char;
}
break;
case 'r':
case 'g':
case 'b':
case 't':
arg = current_char;
break;
case ' ':
if (current_number_len > 0) parsed_number = stoi(current_number_string);
if (arg != ' ') callback(command, arg, parsed_number);
arg = ' ';
current_number_len = 0;
fill(begin(current_number_string), end(current_number_string), ' ');
current_number_string[3] = '\0';
break;
case '\n':
if (current_number_len > 0) parsed_number = stoi(current_number_string);
callback(command, arg, parsed_number);
command = arg = ' ';
line_position = parsed_number = current_number_len = 0;
fill(begin(current_number_string), end(current_number_string), ' ');
current_number_string[3] = '\0';
break;
default:
cout << "invalid syntax." << endl;
return 1;
}
}
if (current_char != '\n') line_position++;
total_position++;
current_char = input[total_position];
}
line_position = 0;
return 0;
}

@ -0,0 +1,138 @@
#include <iostream>
//#include <cstring>
using namespace std;
int parse_string(char input[]);
void parse_string_callback(char command, char arg, int parsed_number);
int main() {
char input1[] = "f r20 g120 b255\n";
char input2[] = "b\n";
char input3[] = "t r20\n";
char input4[] = "t r20\nb\nf r20 g120 b255\n";
char input5[] = "t'r3\n";
cout << "parsing string: " << input4 << endl;
return parse_string(input4);
}
void callback(char command, char arg, int parsed_number) {
cout << "command: " << command << " | ";
cout << "arg: " << arg << " | ";
cout << "parsed_number: " << parsed_number << " | ";
cout << endl;
}
int parse_string(char input[]) {
char current_char = input[0];
char command = ' ';
char arg = ' ';
char current_number_string[4] = {' ', ' ', ' ', '\0'};
int line_position = 0;
int total_position = 0;
int current_number_len = 0;
int parsed_number = 0;
while (current_char != '\0') {
if (line_position == 0) {
switch (current_char) {
case 'f':
case 't':
case 'b':
command = current_char;
break;
default:
cout << "invalid command. " << endl;
return 1;
}
} else {
switch (current_char) {
case '0' ... '9':
if (current_number_len < 4) {
current_number_len++;
current_number_string[current_number_len - 1] = current_char;
}
break;
case 'r':
case 'g':
case 'b':
case 't':
arg = current_char;
break;
case ' ':
if (current_number_len > 0) parsed_number = stoi(current_number_string);
if (arg != ' ') callback(command, arg, parsed_number);
arg = ' ';
current_number_len = 0;
fill(begin(current_number_string), end(current_number_string), ' ');
current_number_string[3] = '\0';
break;
case '\n':
if (current_number_len > 0) parsed_number = stoi(current_number_string);
callback(command, arg, parsed_number);
command = arg = ' ';
line_position = parsed_number = current_number_len = 0;
fill(begin(current_number_string), end(current_number_string), ' ');
current_number_string[3] = '\0';
break;
default:
cout << "invalid syntax." << endl;
return 1;
}
}
if (current_char != '\n') {
//cout << "line_position: " << line_position << " | ";
//cout << "current_char: " << (current_char == '\n' ? '\\' : current_char) << " | ";
//cout << "parsed_number: " << parsed_number << " | ";
//cout << "current_number_string: " << current_number_string << " | ";
//cout << "command: " << command << endl;
line_position++;
}
total_position++;
current_char = input[total_position];
}
line_position = 0;
return 0;
}

@ -0,0 +1,29 @@
# ledctl
## Documentation
Each command sent through Serial is a single character followed by arguments in g-code style. For example: `F T200 R0 G0 B107`. All characters must be capitalized.
For any command's parameters, if it is not provided, the initial or last values will be used instead.
If a parameter is repeated, or two parameters that change the same values are used at the same time, the right-most occurrence takes precedence.
### `B` Breathe
Usage `B`
Changes into "Breathe" mode.
### `F` Fade
Usage: `F T<time> R<red> G<green> B<blue>`
Fades into a color specified by `R` `G` `B` in `T` milliseconds. Use `T0` for an instant change. Changes into "Set Color" mode.
Note that on a 328p, the maximum PWM resolution is 256 distinct values. If anything outside of that range is used, it will overflow.
### `T` Tickrate
Usage: `T R<rate> I<interval>`
Changed the ticks-per-second to `R`, or the tick interval by `I` milliseconds.

@ -0,0 +1,95 @@
{
"folders": [
{
"path": ".."
},
{
"path": "../../js-ledctl-gui"
},
{
"path": "../../../Downloads/matrixclienttest"
}
],
"settings": {
"editor.insertSpaces": false,
"files.associations": {
"cstring": "cpp",
"algorithm": "cpp",
"associative_base": "cpp",
"basic_definitions": "cpp",
"bitset": "cpp",
"cctype": "cpp",
"char_traits": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"complex": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"deque": "cpp",
"exception": "cpp",
"func_exception": "cpp",
"functional": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"istream_helpers": "cpp",
"iterator": "cpp",
"iterator_base": "cpp",
"limits": "cpp",
"list": "cpp",
"locale": "cpp",
"map": "cpp",
"memory": "cpp",
"new": "cpp",
"numeric": "cpp",
"ostream": "cpp",
"ostream_helpers": "cpp",
"queue": "cpp",
"serstream": "cpp",
"set": "cpp",
"sstream": "cpp",
"stack": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"string": "cpp",
"string_iostream": "cpp",
"type_traits": "cpp",
"typeinfo": "cpp",
"utility": "cpp",
"valarray": "cpp",
"vector": "cpp",
"array": "cpp",
"atomic": "cpp",
"strstream": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"chrono": "cpp",
"compare": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"cstdint": "cpp",
"unordered_map": "cpp",
"memory_resource": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"fstream": "cpp",
"mutex": "cpp",
"ranges": "cpp",
"stop_token": "cpp",
"thread": "cpp",
"cinttypes": "cpp"
}
}
}

@ -0,0 +1,274 @@
#define RED_LED 5
#define GREEN_LED 3
#define BLUE_LED 6
#define STATUS_LED 4
#define MAX_NUMBER_DIGITS 4
using namespace std;
int tps = 33;
unsigned long current_ms = millis();
unsigned long tick_interval_tracker = 0;
unsigned int tick_interval = 1000 / tps;
int leds[] = {RED_LED, GREEN_LED, BLUE_LED};
int led_iterator = 0;
int mode = 0; // 0 = breathe, 1 = set color
float current_vals[] = {0, 0, 0};
int breathe_increments[] = {1, 2, 4};
int breathe_directions[] = {0, 0, 0};
int target_vals[] = {0, 0, 0};
int fade_ticks = 0;
int fade_ms = 0;
float fade_increments[] = {0, 0, 0};
char current_char = ' ';
char command = ' ';
char arg = ' ';
char current_number_string[MAX_NUMBER_DIGITS + 1];
int position = 0;
int current_number_len = 0;
int parsed_number = 0;
bool end_of_line = 0;
void setup() {
Serial.begin(9600);
Serial.println("ready.");
pinMode(RED_LED, OUTPUT);
pinMode(GREEN_LED, OUTPUT);
pinMode(BLUE_LED, OUTPUT);
pinMode(STATUS_LED, OUTPUT);
reset_number_string();
}
void loop() {
if (Serial.available()) {
current_char = Serial.read();
if (position == 0) {
switch (current_char) {
case 'F':
case 'T':
case 'B':
command = current_char;
break;
default:
Serial.println("invalid command.");
Serial.flush();
command = arg = ' ';
position = parsed_number = 0;
reset_number_string();
break;
}
} else {
switch (current_char) {
case '0' ... '9':
if (current_number_len < MAX_NUMBER_DIGITS) {
current_number_len++;
current_number_string[current_number_len - 1] = current_char;
}
break;
case 'R':
case 'G':
case 'B':
case 'T':
case 'I':
arg = current_char;
break;
case ' ':
if (current_number_len > 0) parsed_number = atoi(current_number_string);
if (arg != ' ') callback();
arg = current_char = ' ';
reset_number_string();
break;
case '\n':
if (current_number_len > 0) parsed_number = atoi(current_number_string);
end_of_line = true;
callback();
command = arg = ' ';
position = parsed_number = 0;
reset_number_string();
break;
default:
Serial.println("invalid syntax.");
Serial.flush();
command = arg = ' ';
position = parsed_number = 0;
reset_number_string();
}
}
if (current_char == '\n') {
end_of_line = false;
Serial.println("ok.");
} else position++;
}
if (millis() - tick_interval_tracker >= tick_interval) {
tick_interval_tracker += tick_interval;
execute_tick();
}
}
void callback() {
switch (command) {
case 'B':
mode = 0;
break;
case 'F':
switch (arg) {
case 'T':
fade_ms = parsed_number;
break;
case 'R':
target_vals[0] = parsed_number;
break;
case 'G':
target_vals[1] = parsed_number;
break;
case 'B':
target_vals[2] = parsed_number;
break;
}
if (end_of_line == true) {
if (fade_ms <= tick_interval) {
mode = 1;
fade_ticks = 0;
} else {
mode = 1;
fade_ticks = ceil(fade_ms / (float) tick_interval);
led_iterator = 0;
while (led_iterator < 3) {
fade_increments[led_iterator] = -((current_vals[led_iterator] - target_vals[led_iterator]) / (float) fade_ticks);
led_iterator++;
}
}
}
break;
case 'T':
if (arg == 'R') {
tps = parsed_number;
tick_interval = 1000 / tps;
} else if (arg == 'I') {
tick_interval = parsed_number;
tps = 1000 / tick_interval;
}
break;
}
}
void reset_number_string() {
for (int i = 0; i < MAX_NUMBER_DIGITS; i++) current_number_string[i] = ' ';
current_number_string[MAX_NUMBER_DIGITS] = '\0';
current_number_len = 0;
}
void execute_tick() {
if (mode == 0) {
led_iterator = 0;
while (led_iterator < 3) {
if (current_vals[led_iterator] <= 0 || current_vals[led_iterator] >= 255) breathe_increments[led_iterator] = -breathe_increments[led_iterator];
analogWrite(leds[led_iterator], current_vals[led_iterator]);
current_vals[led_iterator] = constrain(current_vals[led_iterator] + breathe_increments[led_iterator], 0, 255);
led_iterator++;
}
} else if (mode == 1) {
if (fade_ticks > 0) {
led_iterator = 0;
while (led_iterator < 3) {
current_vals[led_iterator] += fade_increments[led_iterator];
analogWrite(leds[led_iterator], current_vals[led_iterator]);
led_iterator++;
}
fade_ticks--;
} else if (fade_ticks == 0) {
Serial.println("done.");
fade_ticks--;
}
}
}
Loading…
Cancel
Save