I've made an Arduino program to run on my Teensy 3.1 board. It accepts characters and strings sent to a Bluetooth module (BC417) from any Bluetooth-enabled device and uses these to power certain pins on my 8x8 LED matrix.
I believe the code works, but I haven't been able to test it fully yet. I'm hoping (if it's the right subject for this site) that there are ways the code can be improved. I'm still somewhat a beginner with Arduino programming, and I know there are many functions I don't know about that will probably be useful for me now and in the future
#define MyBtooth Serial2
#define dw digitalWrite
char incomingChar;
String inString;
bool stream;
//********************************************************
// Setup
//********************************************************
void setup() {
for (int x = 0; x <= 23; x++) {
if ((x >= 0) && (x <= 11) || (x >= 14) && (x <= 23)) {
pinMode(x, OUTPUT);
}
else {}
}
// for (int x = 14; x <= 23; x++) {
// dw(x, HIGH); //TAKE THIS OUT TEMP
// }
Serial.begin(9600);
pinMode(13, OUTPUT);
MyBtooth.begin(9600);
}
//********************************************************
// Main Loop
//********************************************************
void loop() {
Serial.println("How do you want to control the RGB matrix?");
Serial2.println("How do you want to control the RGB matrix?");
Serial.println("Send 'Bluetooth' for Bluetooth control and 'Serial' for USB control.");
Serial2.println("Send 'Bluetooth' for Bluetooth control and 'Serial' for USB control.");
Serial.println("Sending 'Cancel' at any time after making a choice will return you to this menu.");
Serial2.println("Sending 'Cancel' at any time after making a choice will return you to this menu.");
String choice = Serial.readString();
String choicebt = Serial2.readString();
if ((choice.toUpperCase() == "BLUETOOTH") || (choicebt.toUpperCase() == "BLUETOOTH")) {
BTControl();
}
else if ((choice.toUpperCase() == "SERIAL") || (choicebt.toUpperCase() == "SERIAL")) {
serialControl();
}
else{}
}
void serialControl() {
while (true) {
if (Serial.available() > 0) {
incomingChar = Serial.read();
Serial.print("USB received: ");
Serial.println(incomingChar);
MyBtooth.print("USB received:");
MyBtooth.println(incomingChar);
switches();
}
String cancel = Serial.readString();
if (cancel.toUpperCase() == "CANCEL") {
break;
}
}
}
void BTControl() {
while (true) {
if (MyBtooth.available() > 0) {
incomingChar = MyBtooth.read();
Serial.print("UART received: ");
Serial.println(incomingChar);
MyBtooth.print("UART received:");
MyBtooth.println(incomingChar);
switches();
}
String cancel = Serial2.readString();
if (cancel.toUpperCase() == "CANCEL") {
break;
}
}
}
void letterA() {
for (int x = 0; x <= 100000; x++) {
dw(0, HIGH);
dw(1, HIGH);
dw(6, HIGH);
dw(7, HIGH);
dw(21, HIGH);
dw(3, LOW);
dw(4, LOW);
delay(0.5);
dw(21, LOW);
dw(3, HIGH);
dw(4, HIGH);
dw(2, LOW);
dw(5, LOW);
dw(20, HIGH);
delay(0.5);
dw(20, LOW);
dw(2, HIGH);
dw(5, HIGH);
dw(1, LOW);
dw(6, LOW);
dw(19, HIGH);
dw(18, HIGH);
dw(17, HIGH);
dw(16, HIGH);
dw(15, HIGH);
dw(14, HIGH);
delay(0.5);
dw(14, LOW);
dw(15, LOW);
dw(16, LOW);
dw(17, LOW);
dw(19, LOW);
dw(1, HIGH);
dw(6, HIGH);
delay(0.5);
}
delay(200);
}
void letterB() {
for(int x = 0; x <= 500; x++) {
dw(0, HIGH);
dw(1, LOW);
dw(2, HIGH);
dw(3, HIGH);
dw(4, HIGH);
dw(5, HIGH);
dw(6, HIGH);
dw(7, HIGH);
dw(21, HIGH);
dw(20, HIGH);
dw(19, HIGH);
dw(18, HIGH);
dw(17, HIGH);
dw(16, HIGH);
dw(15, HIGH);
dw(14, HIGH);
delay(1);
dw(21, LOW);
dw(14, LOW);
dw(18, LOW);
dw(5, LOW);
dw(1, HIGH);
delay(1);
dw(1, HIGH);
dw(5, HIGH);
dw(2, LOW);
dw(3, LOW);
dw(4, LOW);
dw(21, HIGH);
dw(14, HIGH);
dw(18, HIGH);
dw(20, LOW);
dw(19, LOW);
dw(17, LOW);
dw(16, LOW);
dw(15, LOW);
delay(1);
dw(2, HIGH);
dw(3, HIGH);
dw(4, HIGH);
dw(14, LOW);
dw(18, LOW);
delay(1);
}
delay(200);
}
void letterC() {
for(int x = 0; x <= 1500; x++) {
dw(0, HIGH);
dw(1, LOW);
dw(2, HIGH);
dw(3, HIGH);
dw(4, HIGH);
dw(5, HIGH);
dw(6, HIGH);
dw(7, HIGH);
dw(20, HIGH);
dw(19, HIGH);
dw(18, HIGH);
dw(17, HIGH);
dw(16, HIGH);
dw(15, HIGH);
delay(1);
dw(6, LOW);
dw(19, LOW);
dw(18, LOW);
dw(17, LOW);
dw(16, LOW);
delay(1);
dw(1, HIGH);
dw(6, HIGH);
dw(2, LOW);
dw(3, LOW);
dw(4, LOW);
dw(5, LOW);
dw(20, LOW);
dw(15, LOW);
dw(21, HIGH);
dw(14, HIGH);
delay(1);
dw(21, LOW);
dw(14, LOW);
delay(1);
}
delay(200);
}
void letterW() {
for (int x = 0; x <= 80000; x++) {
dw(21, HIGH);
dw(0, LOW);
dw(7, LOW);
dw(1, HIGH);
dw(2, HIGH);
dw(3, HIGH);
dw(4, HIGH);
dw(5, HIGH);
dw(6, HIGH);
delay(0.5);
dw(21, LOW);
dw(20, HIGH);
delay(0.5);
dw(20, LOW);
dw(19, HIGH);
delay(0.5);
dw(19, LOW);
dw(18, HIGH);
delay(0.5);
dw(18, LOW);
dw(0, HIGH);
dw(7, HIGH);
dw(1, LOW);
dw(6, LOW);
dw(17, HIGH);
delay(0.5);
dw(17, LOW);
dw(16, HIGH);
delay(0.5);
dw(16, LOW);
dw(15, HIGH);
delay(0.5);
dw(15, LOW);
dw(1, HIGH);
dw(6, HIGH);
dw(2, LOW);
dw(5, LOW);
dw(14, HIGH);
delay(0.5);
dw(14, LOW);
dw(2, HIGH);
dw(5, HIGH);
dw(3, LOW);
dw(4, LOW);
dw(15, HIGH);
delay(0.5);
dw(15, LOW);
dw(3, HIGH);
dw(4, HIGH);
delay(0.5);
}
delay(200);
}
void letterZ() {
for (int x = 0; x <= 100000; x++) {
dw(21, HIGH);
dw(14, HIGH);
dw(0, LOW);
dw(1, LOW);
dw(2, LOW);
dw(3, LOW);
dw(4, LOW);
dw(5, LOW);
dw(6, LOW);
dw(7, LOW);
delay(0.5);
dw(0, HIGH);
dw(1, HIGH);
dw(2, HIGH);
dw(3, HIGH);
dw(4, HIGH);
dw(5, HIGH);
dw(7, HIGH);
dw(21, LOW);
dw(14, LOW);
dw(20, HIGH);
delay(0.5);
dw(20, LOW);
dw(6, HIGH);
dw(19, HIGH);
dw(5, LOW);
delay(0.5);
dw(19, LOW);
dw(5, HIGH);
dw(18, HIGH);
dw(4, LOW);
delay(0.5);
dw(18, LOW);
dw(4, HIGH);
dw(17, HIGH);
dw(3, LOW);
delay(0.5);
dw(17, LOW);
dw(3, HIGH);
dw(16, HIGH);
dw(2, LOW);
delay(0.5);
dw(16, LOW);
dw(2, HIGH);
dw(15, HIGH);
dw(1, LOW);
delay(0.5);
dw(15, LOW);
delay(0.5);
}
delay(200);
}
void switches() {
/*
REFERENCE TABLE FOR ON/OFF CHARS
PIN NO. CHAR
0 ON a
1 ON b
2 ON c
3 ON d
4 ON e
5 ON f
6 ON g
7 ON h
14 ON 1
15 ON 2
16 ON 3
17 ON 4
18 ON 5
19 ON 6
20 ON 7
21 ON 8
0 OFF i
1 OFF j
2 OFF k
3 OFF l
4 OFF m
5 OFF n
6 OFF o
7 OFF p
14 OFF 9
15 OFF 0
16 OFF q
17 OFF r
18 OFF s
19 OFF t
20 OFF u
21 OFF v
ALL LETTER FUNCTIONS USE THEIR CORRESPSONDNG CAPITAL LETTER
'A' == letterA();, 'B' == letterB();, etc.
*/
switch (incomingChar) {
//LETTERS
case 'A':
letterA();
break;
case 'B':
letterB();
break;
case 'C':
letterC();
break;
case 'W':
letterW();
break;
case 'Z':
letterZ();
break;
//GROUND "ON"
case 'a':
dw(0, LOW);
break;
case 'b':
dw(1, LOW);
break;
case 'c':
dw(2, LOW);
break;
case 'd':
dw(3, LOW);
break;
case 'e':
dw(4, LOW);
break;
case 'f':
dw(5, LOW);
break;
case 'g':
dw(6, LOW);
break;
case 'h':
dw(7, LOW);
break;
//GROUND "OFF"
case 'i':
dw(0, HIGH);
break;
case 'j':
dw(1, HIGH);
break;
case 'k':
dw(2, HIGH);
break;
case 'l':
dw(3, HIGH);
break;
case 'm':
dw(4, HIGH);
break;
case 'n':
dw(5, HIGH);
break;
case 'o':
dw(6, HIGH);
break;
case 'p':
dw(7, HIGH);
break;
//POSITIVE ON
case '1':
dw(14, HIGH);
break;
case '2':
dw(15, HIGH);
break;
case '3':
dw(16, HIGH);
break;
case '4':
dw(17, HIGH);
break;
case '5':
dw(18, HIGH);
break;
case '6':
dw(19, HIGH);
break;
case '7':
dw(20, HIGH);
break;
case '8':
dw(21, HIGH);
break;
//POSITIVE OFF
case '9':
dw(14, HIGH);
break;
case '0':
dw(15, HIGH);
break;
case 'q':
dw(16, HIGH);
break;
case 'r':
dw(17, HIGH);
break;
case 's':
dw(18, HIGH);
break;
case 't':
dw(19, HIGH);
break;
case 'u':
dw(20, HIGH);
break;
case 'v':
dw(21, HIGH);
break;
//ALL OFF
case 'y':
dw(0, HIGH);
dw(1, HIGH);
dw(2, HIGH);
dw(3, HIGH);
dw(4, HIGH);
dw(5, HIGH);
dw(6, HIGH);
dw(7, HIGH);
dw(14, LOW);
dw(15, LOW);
dw(16, LOW);
dw(17, LOW);
dw(18, LOW);
dw(19, LOW);
dw(20, LOW);
dw(21, LOW);
break;
//ALL ON
case 'z':
dw(0, LOW);
dw(1, LOW);
dw(2, LOW);
dw(3, LOW);
dw(4, LOW);
dw(5, LOW);
dw(6, LOW);
dw(7, LOW);
dw(14, HIGH);
dw(15, HIGH);
dw(16, HIGH);
dw(17, HIGH);
dw(18, HIGH);
dw(19, HIGH);
dw(20, HIGH);
dw(21, HIGH);
break;
}
}
Is there anything that wouldn't work, anything that could be improved or anything that could be done in a better way? I usually learn by testing, but I made most of this without access to my Teensy. The Verify
function comes back clean, but anything I can fix and thus learn from would be very helpful.
2 Answers 2
Remove duplication
There's clearly some duplication in your code, such as:
Serial.println("How do you want to control the RGB matrix?");
Serial2.println("How do you want to control the RGB matrix?");
As you seem to commonly write the same string to both Serial
and MyBtooth
, it's probably worth defining a function that simply does that and using it instead:
void println(const char *text) {
Serial.println(text);
MyBtooth.println(text);
}
I'd also consider refactoring this:
String choice = Serial.readString();
String choicebt = Serial2.readString();
if ((choice.toUpperCase() == "BLUETOOTH") || (choicebt.toUpperCase() == "BLUETOOTH")) {
BTControl();
}
else if ((choice.toUpperCase() == "SERIAL") || (choicebt.toUpperCase() == "SERIAL")) {
serialControl();
}
else{}
To something like this:
setupCommControl(Serial.readString());
setupCommControl(MyBtooth.readString());
Where:
void setupCommControl(const char *choice) {
if (choice.toUpperCase() == "BLUETOOTH") {
BTControl();
}
else if (choice.toUpperCase() == "SERIAL") {
serialControl();
}
}
You also seem to write to ordered ranges of pins like this:
dw(0, LOW);
dw(1, LOW);
dw(2, LOW);
dw(3, LOW);
dw(4, LOW);
dw(5, LOW);
dw(6, LOW);
dw(7, LOW);
Again it might be worth writing a utility method something like this (I'm not sure of the type for pinState), where direction is either 1 (incrementing range) or -1 (decrementing range):
void dwRange(int startPin, int endPin, int direction, int pinState) {
for(int pin = startPin; pin <= endPin; pin += direction) {
dw(pin, pinState);
}
}
Called as:
dwRange(0, 7, 1, LOW);
There may also be scope for doing a similar reduction in your large case statement. Something like:
if(incomingChar >= 'a' && incomingChar <= 'h') {
dw(incomingChar - 'a', LOW);
}
Would remove:
case 'a':
dw(0, LOW);
break;
case 'b':
dw(1, LOW);
break;
case 'c':
dw(2, LOW);
break;
case 'd':
dw(3, LOW);
break;
case 'e':
dw(4, LOW);
break;
case 'f':
dw(5, LOW);
break;
case 'g':
dw(6, LOW);
break;
case 'h':
dw(7, LOW);
break;
Serial2 Vs MyBtooth
It looks like you started off using Serial2
, then defined MyBtooth
to make it more explicit when you were talking to blue tooth vs serial. There are some lingering references to Serial2
in the code that should be updated so that it is consistent throughout.
-
\$\begingroup\$ Thanks for this. I've since moved on from this revision of the code, but some of this will certainly be helpful in what I have now. \$\endgroup\$TheWanderer– TheWanderer2016年06月14日 23:32:45 +00:00Commented Jun 14, 2016 at 23:32
There might be a cleaner way to represent the output going to the LEDs. Can you encode the letters into a 2d 8x8 grid like:
int [][] a = {
{0, 0, 0, 1, 1, 0, 0, 0},
{0, 0, 1, 0, 0, 1, 0, 0},
{0, 0, 1, 0, 0, 1, 0, 0},
{0, 1, 0, 0, 0, 0, 1, 0},
{0, 1, 1, 1, 1, 1, 1, 0},
{0, 1, 0, 0, 0, 0, 1, 0},
{0, 1, 0, 0, 0, 0, 1, 0},
{0, 1, 0, 0, 0, 0, 1, 0}
};
or
String a =
"...00..."
+ "..0..0.."
+ "..0..0.."
+ ".0....0."
+ ".000000."
+ ".0....0."
+ ".0....0."
+ ".0....0.";
Then you would have a function that converts this version into the format that the pins expect. That way you have an easy way to edit and construct the LED patterns.
I'm not sure if this will work because I don't know the interface between the output pins and the 8x8 LED array. Do the letters come pre-programmed into the 8x8 array or do you have one pin for each LED?
-
\$\begingroup\$ had to make them manually \$\endgroup\$TheWanderer– TheWanderer2016年07月24日 01:47:31 +00:00Commented Jul 24, 2016 at 1:47
BTControl()
readsinString
but never uses it. \$\endgroup\$