Hey everyone I'm working on a project for my dad to make a mini firework launching module, and I'm trying to get it to read time (ms), Event (fire), and Cue (which is for the Ematch), I have 8 'Cues i can use. For some reason it will not read "Cues" but looks like it reads everything else. I know little to nothing about coding but this is what I have so far.
For the csv. file I'm trying to have it read this format and understand it. I've tried everything I know but cant get it to "load" or "arm" the cues at all. Any help at all would be greatly appreciated, or push in the right direction!
Time (ms),Event,Cue
1000,Fire,1
2000,Fire,2
3000,Fire,3
Serial Monitor
23:15:13.501 -> Initializing SD card...
23:15:13.945 -> SD card ready!
23:15:13.945 -> Reading cues from file...
23:15:13.977 -> Line: Time (ms),E
23:15:14.010 -> Line: 1000,Fire,1
23:15:14.010 -> Line: 2000,Fire,2
23:15:14.041 -> Line: 3000,Fire,3
23:15:14.073 -> Cues loaded: 0
23:15:14.073 -> Waiting for trigger on D9...
23:15:14.106 -> Trigger received! Starting show...
23:15:14.143 -> Show complete.
#include <SPI.h>
#include <SD.h>
const int chipSelect = 10;
const int triggerPin = 9; // PC817 output connected here
const int muxS[4] = {2, 3, 4, 5}; // Multiplexer control pins S0–S3
const int sigPin = 8; // Multiplexer SIG pin changed to D8
struct Cue {
unsigned long timeMs;
int channel; // 0–7 for C0–C7
};
#define MAX_CUES 100
Cue cueList[MAX_CUES];
int cueCount = 0;
void setup() {
Serial.begin(9600);
delay(1000); // Ensure Serial is ready
pinMode(triggerPin, INPUT_PULLUP);
for (int i = 0; i < 4; i++) {
pinMode(muxS[i], OUTPUT);
digitalWrite(muxS[i], LOW);
}
pinMode(sigPin, OUTPUT);
digitalWrite(sigPin, LOW);
Serial.println("Initializing SD card...");
SPI.setClockDivider(SPI_CLOCK_DIV8);
if (!SD.begin(chipSelect)) {
Serial.println("SD initialization failed!");
return;
}
Serial.println("SD card ready!");
File file = SD.open("show.csv");
if (!file) {
Serial.println("Failed to open show.csv");
return;
}
Serial.println("Reading cues from file...");
while (file.available() && cueCount < MAX_CUES) {
String line = file.readStringUntil('\n'); //
line.trim();
if (line.startsWith("\\xEF\\xBB\\xBF")) {
line = line.substring(3); // Strip BOM
}
Serial.print("Line: ");
Serial.println(line);
if (line.length() == 0 || !isDigit(line[0])) continue;
int comma1 = line.indexOf(',');
int comma2 = nthIndexOf(line, ',', 1);
int comma4 = nthIndexOf(line, ',', 3);
int comma5 = nthIndexOf(line, ',', 4);
if (comma1 == -1 || comma2 == -1 || comma4 == -1 || comma5 == -1) continue;
String eventType = line.substring(comma1 + 1, comma2);
eventType.trim();
if (!eventType.equalsIgnoreCase("Fire")) continue;
unsigned long time = line.substring(0, comma1).toInt();
int cue = line.substring(comma4 + 1, comma5).toInt();
if (cue >= 1 && cue <= 8) {
cueList[cueCount].timeMs = time;
cueList[cueCount].channel = cue - 1;
Serial.print("Loaded cue ");
Serial.print(cue);
Serial.print(" at ");
Serial.print(time);
Serial.println("ms");
cueCount++;
}
}
file.close();
Serial.print("Cues loaded: ");
Serial.println(cueCount);
Serial.println("Waiting for trigger on D9...");
}
void loop() {
if (digitalRead(triggerPin) == LOW) {
Serial.println("Trigger received! Starting show...");
runShow();
while (true);
}
}
void runShow() {
unsigned long startTime = millis();
for (int i = 0; i < cueCount; i++) {
while (millis() - startTime < cueList[i].timeMs) {
// wait
}
fireCue(cueList[i].channel);
}
Serial.println("Show complete.");
}
void fireCue(int channel) {
Serial.print("Firing cue on channel ");
Serial.println(channel + 1);
for (int i = 0; i < 4; i++) {
digitalWrite(muxS[i], (channel >> i) & 1);
}
digitalWrite(sigPin, HIGH);
delay(200); // pulse duration
digitalWrite(sigPin, LOW);
}
int nthIndexOf(String str, char c, int n) {
int pos = -1;
for (int i = 0; i < n; i++) {
pos = str.indexOf(c, pos + 1);
if (pos == -1) return -1;
}
return pos;
}