-
-
Save LordQwert/e3ce455e023cf9186234b65fe7004952 to your computer and use it in GitHub Desktop.
Bluetooth controlled LED display
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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