adding Daily Cheer Automaton

adding Daily Cheer Automaton, Arduino and CircuitPython versions
This commit is contained in:
Andy Doro 2020-05-19 12:40:02 -04:00
parent 4988510b3a
commit febefce3ec
7 changed files with 534 additions and 0 deletions

View file

@ -0,0 +1,39 @@
# DAILY CHEER AUTOMATON
## AUTOCHEER DEVICE
code by [Andy Doro](https://andydoro.com/)
using [Adafruit Feather](https://www.adafruit.com/feather) hardware\
will play an MP3 at a specified time each day
## Arduino Version
![Autocheer Arduino](https://github.com/andydoro/autocheer/blob/master/Arduino/assets/autocheer_arduino.jpg "Autocheer Arduino, photo by Andy Doro")
### HARDWARE
* any Feather board, e.g. [Feather M0 Basic Proto](https://www.adafruit.com/product/2772)
* [Adalogger FeatherWing](https://www.adafruit.com/product/2922) for PCF8523 RTC
* & [CR1220 coin cell](https://www.adafruit.com/product/380)
* [Adafruit Music Maker FeatherWing](https://www.adafruit.com/product/3357) for 3.5mm (1/8") audio jack output
* or [Music Maker FeatherWing w/ Amp](https://www.adafruit.com/product/3436) for speaker wire output
* [MicroSD card](https://www.adafruit.com/product/1294) FAT formatted with "cheer.mp3"
* [FeatherWing Tripler](https://www.adafruit.com/product/3417)
* or [Feather Stacking Headers](https://www.adafruit.com/product/2830) for a different form factor
### SOFTWARE
#### LIBRARIES
* [VS1053](https://github.com/adafruit/Adafruit_VS1053_Library) for Music Maker
* [RCTlib](https://github.com/adafruit/RTClib) for RTC
* [DST_RTC](https://github.com/andydoro/DST_RTC) for automatic Daylight Saving Time adjustments
#### AUDIO FILE
cheer.mp3, place on FAT formatted SD card and insert into Music Maker\
suggestion: http://www.orangefreesounds.com/street-crowd-cheering-and-applauding/

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

View file

@ -0,0 +1,269 @@
/*
AUTOCHEER DEVICE
---
code by Andy Doro https://andydoro.com/
using Adafruit Feather hardware
will play an MP3 at a specified time each day
sketch can easily be modified to perform some other functions at the specified time, such as operate physical/analog noisemakers
HARDWARE
---
- any Feather board, e.g. Feather M0 Basic Proto https://www.adafruit.com/product/2772
- Adalogger FeatherWing https://www.adafruit.com/product/2922
- CR1220 coin cell https://www.adafruit.com/product/380
- Music Maker FeatherWing https://www.adafruit.com/product/3357 for 1/8" audio jack output
or Music Maker FeatherWing w/Amp https://www.adafruit.com/product/3436 for speaker wire output
- MicroSD card https://www.adafruit.com/product/1294 FAT formatted with "cheer.mp3"
- FeatherWing Tripler https://www.adafruit.com/product/3417
or Feather Stacking Headers https://www.adafruit.com/product/2830 for a different form factor
SOFTWARE
---
libraries
- VS1053 https://github.com/adafruit/Adafruit_VS1053_Library for Music Maker
- RCTlib https://github.com/adafruit/RTClib for RTC
- DST_RTC https://github.com/andydoro/DST_RTC for Daylight Saving Time adjustments
cheer.mp3, place on FAT formatted SD card and insert into Music Maker
http://www.orangefreesounds.com/street-crowd-cheering-and-applauding/
*/
// Specifically for use with the Adafruit Feather, the pins are pre-set here!
// include SPI, MP3 and SD libraries
#include <SPI.h>
#include <SD.h>
#include <Adafruit_VS1053.h> // https://github.com/adafruit/Adafruit_VS1053_Library
// Date and time functions using a DS3231 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h" // https://github.com/adafruit/RTClib
#include "DST_RTC.h" // download from https://github.com/andydoro/DST_RTC
// These are the pins used
#define VS1053_RESET -1 // VS1053 reset pin (not used!)
// Feather ESP8266
#if defined(ESP8266)
#define VS1053_CS 16 // VS1053 chip select pin (output)
#define VS1053_DCS 15 // VS1053 Data/command select pin (output)
#define CARDCS 2 // Card chip select pin
#define VS1053_DREQ 0 // VS1053 Data request, ideally an Interrupt pin
// Feather ESP32
#elif defined(ESP32)
#define VS1053_CS 32 // VS1053 chip select pin (output)
#define VS1053_DCS 33 // VS1053 Data/command select pin (output)
#define CARDCS 14 // Card chip select pin
#define VS1053_DREQ 15 // VS1053 Data request, ideally an Interrupt pin
// Feather Teensy3
#elif defined(TEENSYDUINO)
#define VS1053_CS 3 // VS1053 chip select pin (output)
#define VS1053_DCS 10 // VS1053 Data/command select pin (output)
#define CARDCS 8 // Card chip select pin
#define VS1053_DREQ 4 // VS1053 Data request, ideally an Interrupt pin
// WICED feather
#elif defined(ARDUINO_STM32_FEATHER)
#define VS1053_CS PC7 // VS1053 chip select pin (output)
#define VS1053_DCS PB4 // VS1053 Data/command select pin (output)
#define CARDCS PC5 // Card chip select pin
#define VS1053_DREQ PA15 // VS1053 Data request, ideally an Interrupt pin
#elif defined(ARDUINO_NRF52832_FEATHER )
#define VS1053_CS 30 // VS1053 chip select pin (output)
#define VS1053_DCS 11 // VS1053 Data/command select pin (output)
#define CARDCS 27 // Card chip select pin
#define VS1053_DREQ 31 // VS1053 Data request, ideally an Interrupt pin
// Feather M4, M0, 328, nRF52840 or 32u4
#else
#define VS1053_CS 6 // VS1053 chip select pin (output)
#define VS1053_DCS 10 // VS1053 Data/command select pin (output)
#define CARDCS 5 // Card chip select pin
// DREQ should be an Int pin *if possible* (not possible on 32u4)
#define VS1053_DREQ 9 // VS1053 Data request, ideally an Interrupt pin
#endif
Adafruit_VS1053_FilePlayer musicPlayer =
Adafruit_VS1053_FilePlayer(VS1053_RESET, VS1053_CS, VS1053_DCS, VS1053_DREQ, CARDCS);
RTC_DS3231 rtc;
//RTC_PCF8523 rtc; // RTC object
DST_RTC dst_rtc; // DST object
// Do you live in a country or territory that observes Daylight Saving Time?
// https://en.wikipedia.org/wiki/Daylight_saving_time_by_country
// Use 1 if you observe DST, 0 if you don't. This is programmed for DST in the US / Canada. If your territory's DST operates differently,
// you'll need to modify the code in the DST_RTC library to make this work properly.
#define OBSERVE_DST 1
// the hour and minute you'd like MP3 to start playing
const int PLAYHOUR = 19; // 24 hour time
const int PLAYMIN = 0;
const int VOLUME = 0; // lower means louder!
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
// if you're using Bluefruit or LoRa/RFM Feather, disable the radio module
//pinMode(8, INPUT_PULLUP);
// Wait for serial port to be opened, remove this line for 'standalone' operation
/*while (!Serial) {
delay(1);
}
*/
delay(500);
Serial.println("\n\nAdafruit VS1053 Feather Test");
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"));
// Set volume for left, right channels. lower numbers == louder volume!
musicPlayer.setVolume(VOLUME, VOLUME);
musicPlayer.sineTest(0x44, 500); // Make a tone to indicate VS1053 is working
if (!SD.begin(CARDCS)) {
Serial.println(F("SD failed, or not present"));
while (1); // don't do anything more
}
Serial.println("SD OK!");
// list files
printDirectory(SD.open("/"), 0);
#if defined(__AVR_ATmega32U4__)
// Timer interrupts are not suggested, better to use DREQ interrupt!
// but we don't have them on the 32u4 feather...
musicPlayer.useInterrupt(VS1053_FILEPLAYER_TIMER0_INT); // timer int
#else
// If DREQ is on an interrupt pin we can do background
// audio playing
musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT); // DREQ int
#endif
// Play a file in the background, REQUIRES interrupts!
/*
Serial.println(F("Playing full track 001"));
musicPlayer.playFullFile("/track001.mp3");
Serial.println(F("Playing track 002"));
musicPlayer.startPlayingFile("/track002.mp3");
*/
// start RTC
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
while (1);
}
// set RTC time if needed
//if (rtc.lostPower()) {
if (! rtc.initialized()) {
Serial.println("RTC lost power, lets set the time!");
// following line sets the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
// DST? If we're in it, let's subtract an hour from the RTC time to keep our DST calculation correct. This gives us
// Standard Time which our DST check will add an hour back to if we're in DST.
if (OBSERVE_DST == 1) {
DateTime standardTime = rtc.now();
if (dst_rtc.checkDST(standardTime) == true) { // check whether we're in DST right now. If we are, subtract an hour.
standardTime = standardTime.unixtime() - 3600;
}
rtc.adjust(standardTime);
}
}
}
void loop() {
// put your main code here, to run repeatedly:
// check time
if (OBSERVE_DST == 1) {
DateTime theTime = dst_rtc.calculateTime(rtc.now()); // takes into account DST
} else {
DateTime theTime = rtc.now(); // use if you don't need DST
}
printTheTime(theTime);
byte theHour = theTime.hour();
byte theMinute = theTime.minute();
//check whether it's time to play mp3
if (theHour == PLAYHOUR && theMinute == PLAYMIN) {
Serial.println(F("Playing full track"));
musicPlayer.playFullFile("/cheer.mp3");
}
// only check every second
delay(1000);
}
// File listing helper
void printDirectory(File dir, int numTabs) {
while (true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
//Serial.println("**nomorefiles**");
break;
}
for (uint8_t i = 0; i < numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs + 1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
entry.close();
}
}
// print time to serial
void printTheTime(DateTime theTimeP) {
Serial.print(theTimeP.year(), DEC);
Serial.print('/');
Serial.print(theTimeP.month(), DEC);
Serial.print('/');
Serial.print(theTimeP.day(), DEC);
Serial.print(' ');
Serial.print(theTimeP.hour(), DEC);
Serial.print(':');
Serial.print(theTimeP.minute(), DEC);
Serial.print(':');
Serial.print(theTimeP.second(), DEC);
Serial.println();
}

View file

@ -0,0 +1,47 @@
# DAILY CHEER AUTOMATON
## AUTOCHEER DEVICE
code by [Andy Doro](https://andydoro.com/)
using [Adafruit Feather](https://www.adafruit.com/feather) hardware\
will play an MP3 at a specified time each day
## CircuitPython Version
![Autocheer CircuitPython](https://github.com/andydoro/autocheer/blob/master/CircuitPython/assets/autocheer_circpy.jpg "Autocheer CircuitPython, photo by Dano Wall")
### HARDWARE
* [Feather M4 Express](https://www.adafruit.com/product/3857) is need because it's fast enough to play back MP3 files
* [Adalogger FeatherWing](https://www.adafruit.com/product/2922) for PCF8523 RTC
* & [CR1220 coin cell](https://www.adafruit.com/product/380)
* [MicroSD card](https://www.adafruit.com/product/1294) FAT formatted with "cheer.mp3"
* [FeatherWing Doubler](https://www.adafruit.com/product/2890)
* or [Feather Stacking Headers](https://www.adafruit.com/product/2830) for a different form factor
* [Headphone Jack](https://www.adafruit.com/product/1699)
### SOFTWARE
requires M4 (ATSAMD51 32-bit Cortex M4 core) or higher and\
CircuitPython version 5.3.0+
#### LIBRARIES
from [library bundle version 5.x](https://circuitpython.org/libraries):
* adafruit_bus_device folder
* adafruit_register folder
* adafruit_pcf8523.mpy
* adafruit_sdcard.mpy
#### AUDIO FILE
cheer.mp3, place on FAT formatted SD card and insert into Music Maker\
suggestion: http://www.orangefreesounds.com/street-crowd-cheering-and-applauding/

Binary file not shown.

After

Width:  |  Height:  |  Size: 143 KiB

View file

@ -0,0 +1,168 @@
# AUTOCHEER DEVICE
# code by Andy Doro
#
# plays an MP3 at a specific time.
#
# uses native CircuitPython mp3 playback
#
# REQUIREMENTS:
# should use M4 (or higher)
# use CircuitPython 5.3.0+
#
#
# HARDWARE:
# Feather M4 Express https://www.adafruit.com/product/3857
# Adalogger https://www.adafruit.com/product/2922
#
#
# TO DO
# ---
# - daylight saving time
# - use built-in NeoPixel as indicator
#
import os
import time
import board
import audiomp3
import audioio
import digitalio
# For hardware I2C (M0 boards) use this line:
import busio as io
# Or for software I2C (ESP8266) use this line instead:
# import bitbangio as io
#import adafruit_ds3231
import adafruit_pcf8523
# SD card
import adafruit_sdcard
import storage
# NeoPixel
#import neopixel
# Use any pin that is not taken by SPI
# For Adalogger FeatherWing: https://learn.adafruit.com/adafruit-adalogger-featherwing/pinouts
# The SDCS pin is the chip select line:
# On ESP8266, the SD CS pin is on GPIO 15
# On ESP32 it's GPIO 33
# On WICED it's GPIO PB5
# On the nRF52832 it's GPIO 11
# On Atmel M0, M4, 328p or 32u4 it's on GPIO 10
# On Teensy 3.x it's on GPIO 10
SD_CS = board.D10 # for M4
# Connect to the card and mount the filesystem.
spi = io.SPI(board.SCK, board.MOSI, board.MISO)
cs = digitalio.DigitalInOut(SD_CS)
sdcard = adafruit_sdcard.SDCard(spi, cs)
vfs = storage.VfsFat(sdcard)
storage.mount(vfs, "/sd")
# Use the filesystem as normal! Our files are under /sd
# This helper function will print the contents of the SD
def print_directory(path, tabs=0):
for file in os.listdir(path):
stats = os.stat(path + "/" + file)
filesize = stats[6]
isdir = stats[0] & 0x4000
if filesize < 1000:
sizestr = str(filesize) + " by"
elif filesize < 1000000:
sizestr = "%0.1f KB" % (filesize / 1000)
else:
sizestr = "%0.1f MB" % (filesize / 1000000)
prettyprintname = ""
for _ in range(tabs):
prettyprintname += " "
prettyprintname += file
if isdir:
prettyprintname += "/"
print('{0:<40} Size: {1:>10}'.format(prettyprintname, sizestr))
# recursively print directory contents
if isdir:
print_directory(path + "/" + file, tabs + 1)
print("Files on filesystem:")
print("====================")
print_directory("/sd")
data = open("/sd/cheer.mp3", "rb")
mp3 = audiomp3.MP3Decoder(data)
#a = audioio.AudioOut(board.A0) # mono
a = audioio.AudioOut(board.A0, right_channel=board.A1) # stereo sound through A0 & A1
i2c = io.I2C(board.SCL, board.SDA) # Change to the appropriate I2C clock & data
# pins here!
# Create the RTC instance:
#rtc = adafruit_ds3231.DS3231(i2c)
rtc = adafruit_pcf8523.PCF8523(i2c)
# Lookup table for names of days (nicer printing).
days = ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")
# selected time
# 24 hour time
playhour = 19
playmin = 0
# pylint: disable-msg=bad-whitespace
# pylint: disable-msg=using-constant-test
# no DST adjustment yet!
if False: # change to True if you want to set the time!
# year, mon, date, hour, min, sec, wday, yday, isdst
t = time.struct_time((2020, 5, 13, 15, 15, 15, 0, -1, -1))
# you must set year, mon, date, hour, min, sec and weekday
# yearday is not supported, isdst can be set but we don't do anything with it at this time
print("Setting time to:", t) # uncomment for debugging
rtc.datetime = t
print()
# pylint: enable-msg=using-constant-test
# pylint: enable-msg=bad-whitespace
# setup NeoPixel
#pixel = neopixel.NeoPixel(board.NEOPIXEL, 1)
# Main loop:
while True:
t = rtc.datetime
# print(t) # uncomment for debugging
print(
"The date is {} {}/{}/{}".format(
days[int(t.tm_wday)], t.tm_mday, t.tm_mon, t.tm_year
)
)
print("The time is {}:{:02}:{:02}".format(t.tm_hour, t.tm_min, t.tm_sec))
if t.tm_hour == playhour and t.tm_min == playmin:
print("it is time!")
# turn NeoPixel green
#pixel[0] = (0, 255, 0)
# play the file
print("playing")
a.play(mp3)
while a.playing:
pass
print("stopped")
# turn NeoPixel off
#pixel[0] = (0, 0, 0)
time.sleep(1) # wait a second

View file

@ -0,0 +1,11 @@
# DAILY CHEER AUTOMATON
## AUTOCHEER DEVICE
code by [Andy Doro](https://andydoro.com/)
using [Adafruit Feather](https://www.adafruit.com/feather) hardware\
will play an MP3 at a specified time each day
sketch can easily be modified to perform some other functions at the specified time, such as operate physical/analog noisemakers
there are Arduino and CircuitPython versions of this project, each using different code and hardware.