4
\$\begingroup\$

This code works, in the same way that a cardboard bicycle works until you cycle through a puddle. It powers a box that plays a sound file in sync with some lights on movement detected by a PIR sensor. Once the sound file has finished it concatenates some text and two random strings from an array and prints it. Once it's done it resets so the motion sensor is active again.

//MUSIC MAKER SETUP
#include <string.h>

#include <SPI.h>
#include <avr/pgmspace.h>
#include <Adafruit_VS1053.h>
#include <SD.h>
#define SHIELD_RESET  -1      // VS1053 reset pin (unused!)
#define SHIELD_CS     7      // VS1053 chip select pin (output)
#define SHIELD_DCS    6      // VS1053 Data/command select pin (output)
#define CARDCS 4     // Card chip select pin
#define DREQ 3       // VS1053 Data request, ideally an Interrupt pin

#include <Adafruit_NeoPixel.h>
#include "SoftwareSerial.h"
#include "Adafruit_Thermal.h"
#include <avr/pgmspace.h>
#include "skull.h"

//PIN USE
//MP3 SHIELD: 3, 4, 6, 7
//PIR SENSOR: A0, left gnd, left 5v
//LIGHTS: 10 for green data in. yellow not used.
//THERMAL PRINTER: 8 and 9

//PRINTER
int printer_TX_Pin = 8;  // This is the yellow wire
int printer_RX_Pin = 9;  // This is the green wire
Adafruit_Thermal printer(printer_RX_Pin, printer_TX_Pin);

//PIXELS!!!
#define PIN 10
#define NUMPIXELS 16 

//PIR SENSOR
#define pir A0
#define led 13

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

Adafruit_VS1053_FilePlayer musicPlayer = Adafruit_VS1053_FilePlayer(SHIELD_RESET, SHIELD_CS, SHIELD_DCS, DREQ, CARDCS);

boolean playing = false;

const char string_0[] PROGMEM = "You have a great need for other people to like and admire you. ";
const char string_1[] PROGMEM = "You have a tendency to be critical of yourself. ";
const char string_2[] PROGMEM = "You have a great deal of unused capacity which you have not turned to your advantage. ";
const char string_3[] PROGMEM = "While you have some personality weaknesses, you are generally able to compensate for them. ";
const char string_4[] PROGMEM = "Your sexual adjustment has presented problems for you. ";
const char string_5[] PROGMEM = "Disciplined and self-controlled outside, you tend to be worrisome and insecure inside. ";
const char string_6[] PROGMEM = "At times you have serious doubts as to whether you have made the right decision or done the right thing. ";
const char string_7[] PROGMEM = "You prefer a certain amount of change and variety and become dissatisfied when hemmed in by restrictions and limitations. ";
const char string_8[] PROGMEM =  "You pride yourself as an independent thinker and do not accept others' statements without satisfactory proof. ";
const char string_9[] PROGMEM = "You have found it unwise to be too frank in revealing yourself to others. ";
const char string_10[] PROGMEM = "At times you are extroverted, affable, sociable, while at other times you are introverted, wary, reserved. ";
const char string_11[] PROGMEM = "Some of your aspirations tend to be pretty unrealistic. ";
const char string_12[] PROGMEM = "Security is one of your major goals in life. ";

const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5, string_6, string_7, string_8, string_9, string_10, string_11, string_12};

void setup() {
  //PRINTER SETUP
  Serial.begin(9600);
  pinMode(7, OUTPUT); digitalWrite(7, LOW);
  printer.begin();

  //PIXELS SETUP
  pixels.begin();

  //PIR SENSOR
  pinMode(pir, INPUT);
  pinMode(led, OUTPUT);
  Serial.begin(9600);

  setPixels(0,0,0,0);
  randomSeed(analogRead(A2));   
  setPixels(0,0,0,0);   
}

void setPixels(int color1, int color2, int color3, int delay_time) {
     for(int i=0;i<NUMPIXELS;i++) {
      pixels.setPixelColor(i, pixels.Color(color1, color2, color3));
      pixels.show();
      delay(delay_time);
    }
};

void blinkPixels(int color1, int color2, int color3, int gap_time, int total) {
  for (int i=0; i<=total; i++) {
    setPixels(color1, color2, color3, 0);
    delay(gap_time);
    setPixels(0, 0, 0, 0);
    delay(gap_time);
  };
}

void loopPixels(int color1, int color2, int color3, int gap_time, int total) {
  for (int i=0; i<=total; i++) {
    setPixels(color1, color2, color3, gap_time);
    setPixels(0, 0, 0, gap_time);
  };
}

void blinkRandom(int total, int gap_time) {
  for (int i=0; i<=total; i++) {
    setPixels(random(256), random(256), random(256), 0);
    delay(gap_time);
  }
}


void loop() {
  int i = digitalRead(pir);

  if (i == 1 && !playing) {
    playing = true;
    Serial.println("saw motion, playing now");

    //START PLAYING SOUND HERE
    if (! musicPlayer.begin()) { // initialise the music player
       Serial.println(F("Couldn't find VS1053, do you have the right pins defined?"));
       while (1);
    }
    Serial.println(F("VS1053 found"));  
    SD.begin(CARDCS);
    musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT);  // DREQ int       
    Serial.write("about to play sound");
    musicPlayer.setVolume(1,1);
    musicPlayer.startPlayingFile("track001.mp3");

    //welcome to the experience
    blinkPixels(255, 255, 255, 50, 10); //10 x 50 - 500ms
    setPixels(255, 255, 255, 0);
    delay(4000);

    //3s: series of tests
    blinkRandom(30, 100);

    //7s: polyfilotrap test
    blinkRandom(20, 100);

    //9.8s test 2
    blinkRandom(40, 100);    

    //12.2s test 3
    blinkRandom(30, 100);   

    //17 excellent neurons

    //23.5 somethings gone wrong
    delay(500);

    for (int i = 255; i>0; i--) {
      setPixels(255,0,0,0);
      pixels.setBrightness(i);
      pixels.show();
      delay(5);
    };  
    pixels.setBrightness(255);    

    //26.8 seconds - wroooong   
    delay(2500); 

    //32 excuse me
    blinkPixels(0, 255, 0, 200, 5);
    loopPixels(0, 255, 0, 50, 1);
    setPixels(0, 0, 0, 1000);

    setPixels(0, 255, 0, 0);    

    //34.5 still here?
    setPixels(0,255,0,0);

    Serial.write("Light show over");
  }

  //AT END OF AUDIO
  if (musicPlayer.stopped() && playing) {        
    setPixels(0,0,0,0);
    Serial.write("Finished. Do printout");

    char buffer[150];
    int rand = random(0,13);
    strcpy_P(buffer, (char*)pgm_read_word(&(string_table[rand]))); // Necessary casts and dereferencing, just copy.
    String text = "Your personalised reading: ";
    String output;
    output = text + buffer;

    rand = random(0,13);    
    strcpy_P(buffer, (char*)pgm_read_word(&(string_table[rand]))); // Necessary casts and dereferencing, just copy.
    output += buffer; 

    Serial.println("FINAL");
    Serial.println(output);

    printer.justify('C');
    printer.feed(1);
    printer.println(output);  //print the reading
    printer.feed(1);

    int seed = random(0,12);
    if (seed<10) {
      int day = random(1,29);
      int month = random(1,13);
      int year = random(2016,2110);

      const char* death_pre = "The date of your death will be:";    
      String death = String(' ');
      String slash = String('/');
      death += day;
      death += slash;
      death += month;
      death += slash;
      death += year;
      printer.println(death_pre);
      printer.println(death);
      printer.feed(3);
    } else if (seed==10) {
      printer.printBitmap(skull_width, skull_height, skull_data);
      printer.println("You will die of electrocution at 19:21 tomorrow");
    } else {
      printer.printBitmap(skull_width, skull_height, skull_data);
      printer.println("You will die in a car accident at 10:13 tomorrow");      
    }

    playing = false;
  }  
}

(There are actually some great cardboard bicycles)

\$\endgroup\$
2

1 Answer 1

5
\$\begingroup\$

I'm not extremely familiar with Arduino development so I might be a bit off but some things I noticed:

  1. color1, color2, color2 are not very descriptive names. If they corresponds to color channels they should be named accordingly like red, green, blue.

  2. You have a couple of methods which take a time like delay_time or gap_time. It might be an absolutely ingrained standard in Arduino development that times are always measured in milliseconds but appending the unit to the name like display_time_ms or gap_time_ms would make it clear to reader what the time unit should be.

  3. I'm not sure why you copy the random word you select into a buffer and then append it to a String object. It looks to me that this is an unnecessary temporary copy. If I read the documentation right this:

    output = text + buffer;
    

    essentially gets transformed into

    output = text.concat(String(buffer))
    

    (given that text and output are String object while buffer is a char[])

    So to me this looks like it could be simplified to:

    int rand = random(0,13);
    char* random_word = (char*)pgm_read_word(&(string_table[rand]));
    String text = "Your personalised reading: ";
    String output = text + random_word;
    

    which eliminates the requirement for the temporary buffer copy.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.