From 73ccf04eadd7210b6109ae6fc45c80dd6a6aab0c Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Sat, 30 Mar 2024 11:02:08 +0100 Subject: [PATCH] Initial commit. --- RiTCh-Lightshow.ino | 286 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 RiTCh-Lightshow.ino diff --git a/RiTCh-Lightshow.ino b/RiTCh-Lightshow.ino new file mode 100644 index 0000000..37d2688 --- /dev/null +++ b/RiTCh-Lightshow.ino @@ -0,0 +1,286 @@ +/* + RiTCh Lightshow + + Simple Arduino based MP3/DMX player which can be triggered by buttons. + + (c)2024 by H. Wirtz + +*/ + +/* + TODO: + - +*/ + +#include +#include +#include +#include +#include "looper.h" + +#define DEBUG 1 + +#define SENSOR_SCHED 10 +#define WORKER_SCHED 100 +#define LED_SCHED 50 +#define LEVEL_CHECK_SCHED 100 +#define DEBUG_SCHED 500 + +#define BUTTON_LONG_PRESS 1000 +#define MIN_TIME_SWITCH_PRESSED 50 +#define LED_NORMAL_BRIGHTNESS 180 +#define LED_PLAY_BRIGHTNESS 20 +#define DMX_MAX_CHANNEL 512 +#define MAX_VOL_LEVEL 30 +#define MAX_DMX_LEVEL 255 + +// Arduino pins +#define POTI1_PIN A1 +#define POTI2_PIN A2 +#define POTI3_PIN A3 +#define POTI4_PIN A4 +#define BUTTON1_PIN 4 +#define BUTTON2_PIN 5 +#define BUTTON3_PIN 6 +#define BUTTON4_PIN 7 +#define DMX_PIN 8 +#define LED_PIN 9 +#define MP3_RX_PIN 10 +#define MP3_TX_PIN 11 +#define BUSY_PIN 12 + +uint8_t button_state; +uint32_t button_time[4] = { 0, 0, 0, 0 }; +uint8_t poti_level[4] = { 0, 0, 0, 0 }; +uint8_t brightness = LED_NORMAL_BRIGHTNESS; + +typedef struct { + uint16_t address = 0; + uint32_t values = 0; + uint16_t steps = 0; + float diff[4] = { 0.0, 0.0, 0.0, 0.0 }; +} dmx_spot; + +dmx_spot spot[1]; + +// schedular +looper sched; + +// setup audio card +SoftwareSerial mySoftwareSerial(MP3_RX_PIN, MP3_TX_PIN); // RX, TX +DFRobotDFPlayerMini myDFPlayer; + +//-------------------------------------------------------------------------------- +// THREADS +//-------------------------------------------------------------------------------- +void button_check(void) { + byte i; + + for (i = 0; i < 4; i++) { + uint16_t b = button(i); + + if (b > BUTTON_LONG_PRESS && !bitRead(button_state, i)) { + // long press + Serial.print(F("Button[")); + Serial.print(i + 1, DEC); + Serial.println(F("]: long")); + button_time[i] = 0; + do_button_long(i); + } else if (b > MIN_TIME_SWITCH_PRESSED && !bitRead(button_state, i)) { + // short press + Serial.print(F("Button[")); + Serial.print(i + 1, DEC); + Serial.println(F("]: short")); + button_time[i] = 0; + do_button_short(i); + } + } +} + +void level_check(void) { + uint8_t i; + uint8_t poti_lvl; + + for (i = 0; i < 4; i++) { + poti_lvl = map(analogRead(poti_pin_by_number(i)), 15, 1023, 0, 255); + if (poti_lvl != poti_level[i]) { + poti_level[i] = poti_lvl; + Serial.print(F("Poti[")); + Serial.print(i + 1, DEC); + Serial.print(F("]: ")); + Serial.println(poti_level[i]); + do_level(i); + } + } +} + +void show_led(void) { + analogWrite(LED_PIN, LED_PLAY_BRIGHTNESS); +} + +void worker(void) { + for (uint8_t s = 0; s < MAX_DMX_SPOTS; s++) { + uint8_t r = (spot[0].values >> 3); + uint8_t g = (spot[0].values >> 2); + uint8_t b = (spot[0].values >> 1); + uint8_t a = (spot[0].values & 0xff); + + if (spot[s].) + } +} + +//-------------------------------------------------------------------------------- +// HELPER FUNCTIONS +//-------------------------------------------------------------------------------- +void do_level(uint8_t p) { + Serial.print("LEVEL "); + Serial.println(p); + + DmxSimple.write(1 + p, poti_level[p]); +} + +void do_button_long(uint8_t b) { + Serial.print("LONG "); + Serial.println(b); +} + +void do_button_short(uint8_t b) { + Serial.print("SHORT "); + Serial.println(b); +} + +uint32_t button(byte button_nr) { + byte button = button_pin_by_number(button_nr); + + if (digitalRead(button) == LOW) { + if (!bitRead(button_state, button_nr)) { + bitSet(button_state, button_nr); + button_time[button_nr] = millis(); + } else { + if (button_time[button_nr] > millis()) + return (0xffff - button_time[button_nr] + millis()); // overflow-protection + else + return (millis() - button_time[button_nr]); + } + } else { + if (bitRead(button_state, button_nr)) { + bitWrite(button_state, button_nr, 0); + if (button_time[button_nr] > millis()) + return (0xffff - button_time[button_nr] + millis()); // overflow-protection + else + return (millis() - button_time[button_nr]); + } + } + return (0); +} + +uint8_t button_pin_by_number(byte n) { + switch (n) { + case 0: + return (BUTTON1_PIN); + break; + case 1: + return (BUTTON2_PIN); + break; + case 2: + return (BUTTON3_PIN); + break; + case 3: + return (BUTTON4_PIN); + break; + } + return (0); +} + +uint8_t poti_pin_by_number(byte n) { + switch (n) { + case 0: + return (POTI1_PIN); + break; + case 1: + return (POTI2_PIN); + break; + case 2: + return (POTI3_PIN); + break; + case 3: + return (POTI4_PIN); + break; + } + return (0); +} + +//-------------------------------------------------------------------------------- +// SYSTEM +//-------------------------------------------------------------------------------- +void setup() { + Serial.begin(9600); + +#ifdef __AVR_ATmega32U4__ + while (!Serial) { + ; // wait for serial port to connect. Needed for Leonardo only + } +#endif + + Serial.println(""); + + mySoftwareSerial.begin(9600); + + // setup poti pins + pinMode(POTI1_PIN, INPUT_PULLUP); + pinMode(POTI2_PIN, INPUT_PULLUP); + pinMode(POTI3_PIN, INPUT_PULLUP); + pinMode(POTI4_PIN, INPUT_PULLUP); + + // setup button pins + pinMode(BUTTON1_PIN, INPUT_PULLUP); + pinMode(BUTTON2_PIN, INPUT_PULLUP); + pinMode(BUTTON3_PIN, INPUT_PULLUP); + pinMode(BUTTON4_PIN, INPUT_PULLUP); + + // setup mp3 busy pin + pinMode(BUSY_PIN, INPUT_PULLUP); + + // setup LED pin + pinMode(LED_PIN, OUTPUT); + + // setup DMX + DmxSimple.usePin(DMX_PIN); + DmxSimple.maxChannel(DMX_MAX_CHANNEL); + + // DMX setup + spot[0].address = 1; + + // setup audio card + Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)")); + + for (uint8_t n = 0; n < 3; n++) { + if (!myDFPlayer.begin(mySoftwareSerial)) { //Use softwareSerial to communicate with mp3. + Serial.print(F("Unable use DFPlayer: ")); + Serial.println(n, DEC); + for (uint8_t i = 0; i < 3; i++) { + analogWrite(LED_PIN, LED_PLAY_BRIGHTNESS); + delay(100); + analogWrite(LED_PIN, LED_PLAY_BRIGHTNESS); + delay(100); + } + } else { + Serial.println(F("DFPlayer Mini online.")); + myDFPlayer.setTimeOut(500); //Set serial communictaion time out 500ms + break; + } + } + + myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD); + + // init schedular + sched.addJob(button_check, SENSOR_SCHED); + sched.addJob(level_check, LEVEL_CHECK_SCHED); + sched.addJob(worker, WORKER_SCHED); + sched.addJob(show_led, LED_SCHED); + Serial.println(""); +} + +void loop() { + sched.scheduler(); +}