Skip to content

Instantly share code, notes, and snippets.

@LordQwert
Created October 9, 2018 00:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LordQwert/e3ce455e023cf9186234b65fe7004952 to your computer and use it in GitHub Desktop.
Save LordQwert/e3ce455e023cf9186234b65fe7004952 to your computer and use it in GitHub Desktop.
Bluetooth controlled LED display
//To break, send via a bluetooth serial: !O04O?
//Then send it again.
//#define FASTLED_ALLOW_INTERRUPTS 0
//#define FASTLED_INTERRUPT_RETRY_COUNT 1
#include <FastLED.h>
#include "BluetoothSerial.h"
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;
#define UPDATES_PER_SECOND 1
#define LED_PINL 16
#define LED_PINR 17
#define NUM_LEDS 150
//Orb - actual # per side
#define BRIGHTNESS 64
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
CRGB ledsl[NUM_LEDS];
CRGB ledsr[NUM_LEDS];
int ggg = 0;
int lag = 100;
char T_start[3] = "!O";//Orb - rename for each.
char T_end[3] = "O?";
char T_ring = 'O';
char ph[8] = "plahold";
int Acc_error = 0;
#define LED_Data_Size 2000
#define Acc_Data_Size 40
char T_data[Acc_Data_Size];
char OrbLED_Data[LED_Data_Size];
int Current_LED_Data_Size = 0;
enum Mode {None, Command, Solid, Pulse, Spin, Bounce, Rainbow};
Mode LED_Mode = None;//enum?
int Mode_Time = 0;
int Mode_Speed = 80;
int Mode_Rate[10] = {2,3,4,6,20,12,20,32,48,80};//8
int Mode_Color[3] = {0,0,0};
int MR_DIV = 4;
//bounce settings
float Bounce_Span = 0.1;
int Bounce_Dead = 4;
float Bounce_Inc = 0.5 / (Bounce_Dead + NUM_LEDS);
//spin settings
float Spin_Span = 0.1;
int Spin_Dead = 4;
float Spin_Inc = 1.0 / (2 * Spin_Dead + 2 * NUM_LEDS);
void setup() {
delay(1000);
pinMode(0,OUTPUT);
pinMode(LED_PINL,OUTPUT);
pinMode(LED_PINR,OUTPUT);
digitalWrite(0,HIGH);//power up blink
delay(2000); //power-up safety delay
digitalWrite(0,LOW);
Serial.begin(115200);
SerialBT.begin("OrbOut");//Orb - Rename for each.
Serial.println("OrbOut initialized");
FastLED.addLeds<LED_TYPE, LED_PINL, COLOR_ORDER>(ledsl, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.addLeds<LED_TYPE, LED_PINR, COLOR_ORDER>(ledsr, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
Serial.println("FastLED initialized");
}
void loop() {
Serial.println("Entering loop");
if (Data_Exchange()) {
Update_LED();
}
Run_LED();
//FastLED.show();
//FastLED.delay(1000 / UPDATES_PER_SECOND); //orb check
delay(1000 / UPDATES_PER_SECOND);
Serial.println("Exiting loop");
}
int Data_Exchange() {
Serial.println("Entering Data Exchange");
Acc_error = 0;
//sprintf(T_data, Fetch_Acc_Data());
strcpy(T_data,Fetch_Acc_Data());//Orb - learn Serial commands and fix this. T_data likely unneeded.
if (Acc_error) {
strcpy(T_data,T_start);
strcat(T_data,"err");
strcat(T_data,T_end);
}
Serial.println("Entering Data Write");
for (int i = 0;i < strlen(T_data);i++){
SerialBT.write(T_data[i]);
}
Serial.println("Exiting Data Write");
Serial.println("Entering Data Read");
if (SerialBT.available()) {
Serial.println("Check1");
//Core 1 panic'ed (IllegalInstruction). Exception was unhandled.
Serial.println(OrbLED_Data);
strcpy(OrbLED_Data,"\0");
//char n;
int i = 0;
char ccc;
Serial.println("Check2");
Serial.println(OrbLED_Data);
Serial.println(strlen(OrbLED_Data));
while (SerialBT.available()) {
Serial.println("Check3");
if (LED_Mode != 0) {
ccc = SerialBT.read();
}
else {
OrbLED_Data[i] = SerialBT.read();
}
i++;
}
Serial.println("Check");
OrbLED_Data[i]=0;
Serial.println(OrbLED_Data);
Serial.println("Exiting Data Read w/ BT");
return (Parse_LED_Data());
}
else {
Serial.println("Exiting Data Read w/o BT");
return (0);
}
}
char *Fetch_Acc_Data() {
Serial.println("Entering Fetch_Acc_Data");
char *Data = (char *)malloc(Acc_Data_Size * sizeof(char));
strcpy(Data,T_start);
strcat(Data,ph);//Orb - get and stringify acc data
strcat(Data,ph);
strcat(Data,ph);
strcat(Data,T_end);
Serial.println("Exiting Fetch_Acc_Data");
return (Data);
}
int Parse_LED_Data() {
Serial.println("Entering Parse_LED_Data");
int reading = 0;
int any_data = 0;
char Parsed[LED_Data_Size];
int j = 0;
Current_LED_Data_Size = 0;
Serial.println("Entering Parse Loop");
for (int i = 0; i < LED_Data_Size; i++) {
if (reading) {
if (OrbLED_Data[i] == T_ring) {
i++;
if (OrbLED_Data[i] == '?') {
reading = 0;
}
else {
Serial.println("Exiting Parse on read error");
return 0;
}
}
else {
Parsed[j] = OrbLED_Data[i];
j++;
Current_LED_Data_Size++;
}
}
else {
if (OrbLED_Data[i] == '!') {
i++;
if (OrbLED_Data[i] == T_ring) {
reading = 1;
any_data = 1;
}
}
}
}
Serial.println("Exiting Parse loop");
strcpy(OrbLED_Data,"");
for (int i = 0;i < Current_LED_Data_Size;i++)
{
OrbLED_Data[i] = Parsed[i];
}
OrbLED_Data[Current_LED_Data_Size++] = 0;
Serial.println("Exiting Parse on normal");
Serial.println(OrbLED_Data);
return any_data;
}
void Update_LED() {
Serial.println("Entering Update_LED");
int New_Mode = OrbLED_Data[0] - '0';
switch(New_Mode) {
case (Command) :{
Serial.println("Case Command");
LED_Mode = Command;
int NUMRGB = 0;
int LED[4];
for (int i=1;i<Current_LED_Data_Size;i++) {
if (OrbLED_Data[i]=='X') { //orb make sure to end data with "X"
Serial.println("LED Color");
Serial.println(LED[NUMRGB]);
NUMRGB++;
if (NUMRGB == 4) {
NUMRGB = 0;
Assign_LED_Data(LED[0],LED[1],LED[2],LED[3]);
}
}
else {
LED[NUMRGB] = 10 * LED[NUMRGB] + (OrbLED_Data[i] - '0');
}
}
}break;
case (None) :{
Serial.println("Case None");
//if (LED_Mode != None) {
LED_Mode = None;
for (int i = 0;i<2*NUM_LEDS;i++) {
Assign_LED_Data(i,0,0,0);
}
//}
}break;
case (Pulse):{
}
case (Spin):{
}
case (Bounce):{
}
case (Rainbow):{
}
default:{
Serial.println("Case default");
if (LED_Mode != (Mode)New_Mode) {
LED_Mode = (Mode)New_Mode;
Mode_Time = 0;
Mode_Speed = Mode_Rate[OrbLED_Data[1] - '0'];
Serial.println("Mode Speed: ");
Serial.println(Mode_Speed);
int NUMRGB = 0;
int j = 0;
Reset_Color();
for (int i = 2;i<Current_LED_Data_Size;i++) {
if (OrbLED_Data[i] == 'X') {
j++;
if (j == 3) {
i = Current_LED_Data_Size;
}
}
else {
Mode_Color[j] = 10 * Mode_Color[j] + OrbLED_Data[i] - '0';
}
}
if (LED_Mode == Solid) {
Serial.println("Assigning solid color");
for (int i = 0;i<2*NUM_LEDS;i++) {
Assign_LED_Data(i,-1,-1,-1);
}
}
else {
for (int i = 0;i<2 * NUM_LEDS;i++) {
Assign_LED_Data(i,0,0,0);
}
}
}
}break;
}
Serial.println("Exiting Update_LED");
}
void Assign_LED_Data(int lednum, int r, int g, int b) {
int lr = 0;
int ln = lednum;
if (r < 0) r = Mode_Color[0];
if (g < 0) g = Mode_Color[1];
if (b < 0) b = Mode_Color[2];
if (lednum > NUM_LEDS) {
lr = 1;
ln = 2 * NUM_LEDS - ln - 1;
}
if (lr) {
ledsr[ln].red = r;
ledsr[ln].green = g;
ledsr[ln].blue = b;
}
else {
ledsl[ln].red = r;
ledsl[ln].green = g;
ledsl[ln].blue = b;
}
}
void Assign_Scaled_LED_Data(int lednum, float k, int r, int g, int b) {
if (r < 0) r = Mode_Color[0];
if (g < 0) g = Mode_Color[1];
if (b < 0) b = Mode_Color[2];
r = ceil(k * r);
g = ceil(k * g);
b = ceil(k * b);
Assign_LED_Data(lednum, r, g, b);
}
//Mode_Color[], Mode_Speed, Mode_Time, UPDATES_PER_SECOND
void Run_LED() {
Serial.println("Entering Run_LED");
//Serial.println(Mode_Time);
//Serial.println(Mode_Color[0]);
//Serial.println(Mode_Color[1]);
//Serial.println(Mode_Color[2]);
float perc = 1.0 * MR_DIV * Mode_Time / (Mode_Speed * UPDATES_PER_SECOND);
Serial.println(perc);
if (perc >= 1) {
Mode_Time = 0;
perc = 0;
}
switch(LED_Mode) {
case (Bounce) :{
//Serial.println("Case Bounce");
float p = 0.5 - fabs(0.5 - perc); //percent height of bounce center
float p2 = (Bounce_Dead - 1) * Bounce_Inc;
float p3;
for (int i = 0;i<NUM_LEDS;i++) {
if (i==0) {
//Serial.println(Bounce_Dead);
//Serial.println(Bounce_Inc);
}
p2 = p2 + Bounce_Inc; //LED position
p3 = fabs(p2 - p); //percent distance of LED to bounce center.
p3 = (0.5 * Bounce_Span - p3) / (0.5 * Bounce_Span);
if (i < 5) {
//Serial.println(p);
//Serial.println(p2);
//Serial.println(p3);
}
if (p3 > 0) {
Assign_Scaled_LED_Data(i,p3,-1,-1,-1);
Assign_Scaled_LED_Data(2 * NUM_LEDS - i,p3,-1,-1,-1);
}
else {
Assign_LED_Data(i,0,0,0);
Assign_LED_Data(i,0,0,0);
}
}
}break;
case (Spin) :{
Serial.println("Case Spin");
float p1 = (Spin_Dead - 1) * Spin_Inc;
//float pr;
float p2;
//float pr2;
for (int i = 0;i<2*NUM_LEDS;i++) {
p1 = p1 + Spin_Inc; //L LED position
//pr = 1 - pl;//watch 'l' vs '1' if uncomment
p2 = fabs(p1 - perc);//percent distance of LED to spin center.
//pr2 = fabs(pr - perc);
p2 = (0.5 * Spin_Span - p2) / (0.5 * Spin_Span);
if (p2 > 0) {
Assign_Scaled_LED_Data(i,p2,-1,-1,-1);
}
else {
Assign_LED_Data(i,0,0,0);
}
}
}break;
case (Pulse) :{
}break;
case (Rainbow) :{
}break;
case (Solid) :{
}
case (Command) :{
}
case (None) :{
Serial.println("Case None/Pulse/Solid/Command");
}
default :{
Serial.println("Case Default");
}break;
}
Mode_Time++;
}
float fabs(float x) {
if (x < 0) {
return -x;
}
return x;
}
void Reset_Color() {
Mode_Color[0] = 0;
Mode_Color[1] = 0;
Mode_Color[2] = 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment