Skip to content
boitarire_sw.ino 5.44 KiB
Newer Older
/*
  Boitarire software

  Plays a sound through an external MP3 module
  when triggered by external sensor : 
  - inclination switch
  - accelerometer module
  - touch sensors
  Configuration is selected through compilation switches.

  created 25 nov 2021
  by Florian Savard

  This example code is in the public domain.

  https://code.electrolab.fr/Flax/boitarire
*/

// Defines - Macros - Constants
#define SENSOR_INCLINATION
#define SENSOR_ACCELEROMETER
#define SENSOR_TOUCHSENSOR1
#define SENSOR_TOUCHSENSOR2

// Other constants
#define PIN_SENSOR_POSITION 9     // Position sensor input
#define PIN_GROUND_SWITCH   7     // MP3 module ground switch command output
#define PLAY_BLANK_DELAY    1000  // Blanking when playing a sound (ms)
#define DELAY_GROUND_OFF    100   // Time of ground cut of MP3 module for re-init (ms)

#ifdef SENSOR_INCLINATION
#define DEBOUNCE_DELAY      200   // Position sensor input debounce (ms)
#endif

// Local variables
String inputString = "";         // a String to hold incoming data
bool stringComplete = false;  // whether the string is complete

#ifdef SENSOR_INCLINATION
int debounce_delay_mem;
bool input_prev, input_now, edge_detect, edge_timeout, edge_timeout_prev;
#endif

int play_blank_mem, ground_off_mem;
bool trig_inclination, trig_accelero, trig_touch1, trig_touch2;
bool play_busy, ground_off;

// Local function prototypes
void ReadPlayState (void);
void WritePlay (void);

// Setup function
void setup() {
  // Initialize serial:
  Serial.begin(9600);
  // Reserve 200 bytes for the inputString:
  inputString.reserve(200);

#ifdef SENSOR_INCLINATION
  // Position sensor input pin - D9 - Input pull-up
  pinMode(PIN_SENSOR_POSITION, INPUT_PULLUP);
#endif

  // LED output for visualisation
  pinMode(LED_BUILTIN, OUTPUT);

  // MP3 module ground switch command - D7 - Output push-pull
  pinMode(PIN_GROUND_SWITCH, OUTPUT);

  play_busy = false;
  play_blank_mem = 0;
  ground_off = false;
  ground_off_mem = 0;

#ifdef SENSOR_INCLINATION
  debounce_delay_mem = 0;
  input_prev = 0;
  input_now = 0;
  edge_detect = false;
  edge_timeout = false;
  edge_timeout_prev = false;
#endif

  // Connect ground for MP3 module
  digitalWrite(PIN_GROUND_SWITCH, HIGH);
}

// Main loop
void loop() {
  // print the string when a newline arrives:
  if (stringComplete) {
    Serial.println(inputString);

    switch (inputString[0])
    {
      case 0x30:
        WritePlay();
        break;
      default:
        break;
    }
    
    // clear the string:
    inputString = "";
    stringComplete = false;
  }

#ifdef SENSOR_INCLINATION
  // Read instantaneous value of position sensor
  input_now = digitalRead(PIN_SENSOR_POSITION);

  // Edge detection
  if ((input_now == 0) && (input_prev == 1))
  {
    edge_detect = true;
    debounce_delay_mem = millis();
  }

  // LED for visualisation
  if (input_now == 1)
  {
    edge_detect = false;
    digitalWrite(LED_BUILTIN, LOW);
  }

  // Debounce delay
  if (edge_detect == true)
  { // If edge detected on position sensor input, inscrease debounce counter
    if ((edge_timeout == false) && (millis() - debounce_delay_mem > DEBOUNCE_DELAY))
    { // If debounce delay reached, set LED and timeout flag
      edge_timeout = true;
      digitalWrite(LED_BUILTIN, HIGH);
    }

    // Edge detection on timeout flag
    if ((edge_timeout == true) && (edge_timeout_prev == false))
    { // Send play command to MP3 module
      trig_inclination = true;
    }
  }
  else
  {
    edge_timeout = false;
  }
#else
  trig_inclination = false;
#endif

  if (trig_inclination == true)
  {
    trig_inclination = false;
    
    if ((play_busy == false) && (ground_off == false))
    {
      play_busy = true;
      WritePlay();
    }
  }
  
  if ((play_busy == true) && (play_blank_mem < PLAY_BLANK_DELAY))
  {
    play_blank_mem++;
  }
  else if (play_blank_mem >= PLAY_BLANK_DELAY)
  {
    play_blank_mem = 0;
    play_busy = false;
    ground_off = true;
    // Disconnect MP3 module - Reset
    digitalWrite(PIN_GROUND_SWITCH, LOW);
  }

  if ((ground_off == true) && (ground_off_mem < DELAY_GROUND_OFF))
  {
    ground_off_mem++;
  }
  else if (ground_off_mem >= DELAY_GROUND_OFF)
  {
    ground_off_mem = 0;
    ground_off = false;
    // Connect MP3 module - Reset
    digitalWrite(PIN_GROUND_SWITCH, HIGH);
  }

  // Update memorisations for edge detection
  input_prev = input_now;
  edge_timeout_prev = edge_timeout;
}

/*
  SerialEvent occurs whenever a new data comes in the hardware serial RX. This
  routine is run between each time loop() runs, so using delay inside loop can
  delay response. Multiple bytes of data may be available.
*/
void serialEvent() {
  while (Serial.available()) {
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag so the main loop can
    // do something about it:
    if (inChar == '\n') {
      stringComplete = true;
    }
  }
}

void ReadPlayState (void)
{
  // Send Play State read request
  Serial.write(170); // 0xAA
  Serial.write(1);   // 0x01
  Serial.write(0);   // 0x00
  Serial.write(171); // 0xAB
}

void WritePlay (void)
{
  // Send Play request
  Serial.write(170); // 0xAA
  Serial.write(2);   // 0x02
  Serial.write(0);   // 0x00
  Serial.write(172); // 0xAC
}