commit
73ccf04ead
@ -0,0 +1,286 @@ |
||||
/*
|
||||
RiTCh Lightshow |
||||
|
||||
Simple Arduino based MP3/DMX player which can be triggered by buttons. |
||||
|
||||
(c)2024 by H. Wirtz <wirtz@parasitstudio.de> |
||||
|
||||
*/ |
||||
|
||||
/*
|
||||
TODO: |
||||
- |
||||
*/ |
||||
|
||||
#include <SoftwareSerial.h> |
||||
#include <DFRobotDFPlayerMini.h> |
||||
#include <DmxSimple.h> |
||||
#include <EEPROM.h> |
||||
#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("<setup begin>"); |
||||
|
||||
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("<setup end>"); |
||||
} |
||||
|
||||
void loop() { |
||||
sched.scheduler(); |
||||
} |
Loading…
Reference in new issue