Okay some people have requested more detailed instructions so I will do my best as it is my first attempt at doing this kind of guide. I hope not to miss anything as I did alot of this stuff in bits and pieces over the span of a couple of weeks. Also cause I’m a new user it wouldn’t let me put very many links into one post so you guys will have to use your googling skills to find some of these sites. Also I wasn’t able to link most the products I bought. Sorry
First up the wiring setup and parts list
Battery - mainly you need a battery that supports through charging aka can be charged and discharged at the same time. This is not whats actually happening in the system but rather just an over simplification however alot of batteries cant support this feature. Although I’m sure you could wire up some step up or down regulators or something another feature that I chose my battery on was the fact it has dual outputs. My battery has one 12 volt output / input and one usb 5volt output. Another reason for choosing my battery was the switch so I can make sure its always on. Alot of battery packs auto sense the output and if it drops too low it shuts off which would be bad for our project. The battery has some cool features like short circuit protection overcharge protection (which is great for any lipo as they tend to blow up… you have been warned) Also the simplicity and capacity made me choose this one. If you went totally diy and used a battery shield for the photon I’m sure the project could soar to new heights cause you could have the photon regulate the charging as well as be able to report battery percentage etc… however here is the battery I chose it also came with a splitter y cable for charging and discharging at the same time. The only downfall I’ve found with this battery is the leds indicating charge level are always on wasting juice… https://www.amazon.com/gp/product/B00ME3ZH7C/ref=oh_aui_detailpage_o06_s00?ie=UTF8&psc=1
Solar Panel
Mainly you need a voltage higher than 12 to be able to charge your 12 volt battery while ideally staying in the voltage range of the hifiberry. Size would be up to you and your playing time. I haven’t done any drain tests and dont plan on it but mine seems to be working great and its small. I chose a cheap 18 volt 4.2 watt solar panel from china on ebay. If worse comes to worse I figured I can always easily add a second panel wired in parallel to get 18 volt 8.4 watts.
Blocking Diode
You may or may not need one depending upon your solar panel choice. The solar panel I bought didn’t have one of these. Solar panels will steal current from the battery when its dark out if you don’t have one of these in place. It just basically blocks current from flowing backwards.
Particle Photon
Self Explanatory
5 volt relay
I wanted a basic adriuno compatible style single channel relay. This way you can power the relay off the 5 volt pin on the particle photon. The relay I chose also fires with a pretty low input signal. (the photons digital pins output 3.3 volts)
Hifiberry Amp+
Self Explainatory
Raspberry PI
This is up to you. I initially started testing the project with a pi3 and it worked great, however, I feel like the pi3 has an overpowered processor for the job we require and is kind of a waste of energy for this application. I got my hands on a Pi zero W and have been using that ever since and its perfect for this application. At the price point of 10 dollars plus shipping (if you can find one) onboard wifi and bluetooth you cant go wrong. I do however have the pi3 running my main squeezebox and airplay server in the house. THe pi3 has all my music on it and streams to all the other players in the house. Since its acting as a server the extra power is great for piece of mind there. I have that same pi 3 outputting to hdmi to my main living room recievers speakers and an amp+ on top that runs to my patio speakers…
Micro SD Card
I chose a cheap 8gb from amazon… anything 8gb and up is plenty
Various electrical connectors
I used some butt splices for my diode and I also found a couple of barrel connectors to be useful throughout but use your imagination.
Speaker wire and outdoor speakers
your choice here. The hifiberry is compatible with speakers between 4 ohms and 8 ohms impedence. With the higher the sensitivity rating the better… I chose some 8ohm outdoor speakers by polk…
On to the wiring excuse the crude drawing
Basically the 12 volt output goes to the y cable one side goes to the solar panel with the diode installed on the positive wire. The other side goes to hifiberry amp+ with the relay in the middle interrupting the positive wire. Out of the 5 volt output is a micro usb cable that powers the particle photon. I then used jumper cables, since my photon had header pins but you could also easily solder, from the VIN pin on the photon which is your voltage in or 5volts to the positive port on the relay. Also connect the grnd pin to the minus. Then just choose any of the D pins or digital pins on the photon I chose D0 and that is what will be reflected in my code unless you change it on your own. Take that digital pin and wire that to the signal part of the relay. The wiring is done yay!
On to the software setup
Particle photon basically follow the directions in the box its really easy. If I remember right you basically download the app turn it on then connect to its wifi network open the app find your network give it the login credentials and your online… If you wanna test your wiring that is easy with the on board tinker app that is loaded by default. Just click the pin you wired the output to change the voltage to high and your relay should click on. click it again to low and it should click off… success.
Go to the particle IDE website and create an account your photon should now be connected to the cloud. Put the particle code that Ill include later and flash the device. Now you are running the custom firmware instead of the default.
Open the smartthings IDE device handlers and create a new device handler. Paste the groovy code save and publish for you. Now go to the devices tab and add a device choose that new device handler we just created name your switch and give it a hub etc… save. Now in the smartthings app you should be able to go to your newly created switch open the preferences and it will ask you for your device ID and the access token (you can find this information on the particle ide website)… don’t share this info with anyone but input that and save it. Now you can test your smartthings click your switch on and it should now turn on and off your relay.
I’ll preface this section on assuming you already have a squeezebox server either by logitechs old equipment or another raspberry pi running max 2 play. You could use this pi player as the server if you wanted to but since its solar and we are shutting it off that’s not the best solution although it is possible. Also the sd card write protection feature that I’ll mention in a bit is not available if you configure this pi as a server.
Go to the max2play website and download the sd card image for the raspberry pi. I’m not going to go into details on this but there are plenty of tutorials out there on how to download an image and get it to boot on the pi… Max2play also has their own community…Quite simply put download the file then extract it if it is compressed. For windows I used a program called win32 disk imager. Write the file to the drive with your sd card in it… If you choose the wrong drive and have other drives attached this will corrupt it… you have been warned. Install the sd card in the raspberry pi and boot it up. Once its booted (the first install may take longer as it sets everything up) you should be able to navigate to the max2play settings by inputting the ip adress of your pi into any browser… Or I believe //max2play.local also works… you can comb your way around settings and there is tons of good info out there on how it works but you’ll get the hang of it. This program is great as you don’t ever need to access the command line to do almost anything its all web interface based. So I of course support the developer and pay his premium account stuff… This gives you access to tons of other cool plugins and one in particular that I find necessary for this project is the sd card protect feature. Raspberry PI’s hate being just unplugged without being shutdown properly. This can corrupt the sd card and then you cant boot without reinstalling everything again. With this feature all the write access can be locked so that this cant or at least is a million times less likely to happen. Since we are switching the pi on and off via a relay I deem it a necessity. I also installed the password protect feature to password protect my settings page. Also its a good idea to chage the ssh password. Set up the sqeezelight client with your hifiberry amp selected. I believe there is an auto setup feature for hifiberry in max2play as well… Super easy if you have questions don’t hesitate to ask but I’m not going to explain every step of the web process here simply because there is already tons of way better more detailed information out there written by people way more organized than me 
Congratulations you should have a working player as a bonus I recommend the ipeng app for controlling the music as its a million times better than the web interface… Also if you want to turn fire tvs or other android devices as a squeezeplayer sb player is an excellent app…
If you need a little guidance on the server setup (which im assuming is best separate from this solar player) navigate to the logitech media servers ip adress and if you used a raspberry pi you first need to enable it in max2play then you should be able to navigate in a browser to “theserversipadress:9000” In here you can password protect your music and the player controls point it to your music library etc… This is also where you install the spotify plugin if you want it. But again not going to dive into that there is plenty out there.
Optionally for more power savings when the pi is running you can follow this guide where basically you ssh into the pi and change some settings. One is disabling the hdmi output cause we dont need it on our solar player and the second is disabling the led. I did both just to help every bit of power we could save. https://www.jeffgeerling.com/blogs/jeff-geerling/raspberry-pi-zero-conserve-energy
Note you might have to enable the sd card write for these functions to work if you enabled it in max2play. Disabling it is easy just navigate to the tab in max2play with the sd protection and enable write until next boot.
On to some of the intricacies of my code.
I set the photon to deep sleep between 2am and 9 am to change that time just change the hour minutes and seconds in front of the multipliers in the following line of code on the photon to change the exact second of the day it goes to sleep and wakes up. You can also change the timezone setting i currently have (-7) for arizona time just change the value to reflect your change from UTC.
// Sets the permenant sleep and wakeup time in seconds
const int secGo2Sleep = 2*3600 + 00*60 + 00;
const int secWakeUp = 9*3600 + 00*60 + 00;
This mode is the only mode that runs on its own for sleep. All the other functions I wrote are called upon via a web request. I found the easiest way to achieve this was with ifttt since they have particle photon support. The first mode I put in was basically to act in case I run goodnight on smartthings. If i run goodnight on smartthings it fires off the following function…
// If I go to bed and run the smartthings goodnight routine this function sleeps the photon a little earlier to save more battery while still waking at the permenant wake time
int gnight(String command)
{
int secnow = Time.local() % 86400; // whats the current second of the day
if (secnow > secWakeUp && command == "goodnight") //runs this time calculation for sleep if goodnight is requested before midnight
{
System.sleep(SLEEP_MODE_DEEP, 86400-secnow+secWakeUp);
return 1;
}
if (secnow < secWakeUp && command == "goodnight") // runs this time calculation for sleep if goodnight is requested after midnight
{
System.sleep(SLEEP_MODE_DEEP, secWakeUp - secnow);
return 1;
}
else
{
return -1;
}
}
So in order to fire this off I need to make an IFTTT recipe that is triggered via maker and then reacts to call the goodnight function on the particle with the command goodnight. I then set up a CoRE piston in smartthings that if my mode changes to night then make web request to the maker channel… Im assuming you all have core and IFTTT. Im not going to dive into that stuff here. This will sleep the photon from the current time until all the way until the wakeup time.
The second function is the away mode and is located in the block here in case you want to tinker with the number of seconds it sleeps or wakes to have a latency that suits you after you arrive home. By defualt I’m having it sleep for 5 minutes wake up and then if im still not home it fires again to sleep go to sleep again for another 5 minutes. This is called upon via ifttt. I was looking into using other methods to achieve this but was the best I could come up with without employing the extra power usage of retained variables etc… SO how it works is when my photon comes back online it sends out a message saying I’m onine and IFTTT can subscirbe to this message so you need to either make an IFTT recipe that responds to the photon coming online which is a default option in IFTTT or use one that subscribes to the additional message I published at the top of my code called “imup with the contents on” I then have this activate a stringify flow. For my stringify flow I use basically if i get the IFTTT trigger but only if my mode is away then tell ifttt. I then set up a second IFTTT recipe that says if the above stringify flow triggered to call the particle function mode with the contents “away” and this happens over and over until your mode changes to home. To be triggered into away mode initially requires another recpie in both stringify and IFTT to achieve this I basically in stringify set up a flow that if my mode changes to away then trigger an iftt recipe. THe ifttt recipe says if that strigify away mode flow ran to fire the same funtion command of away to start the sleep cycle the first time…
int mod(String command)
{
if (command == "away")
{
System.sleep(SLEEP_MODE_DEEP, 300);
return 1;
}
else
{
return -1;
}
}
You need to setup stringify however you want to achieve the “mode changes” I wanted them directly correlated to my smartthings modes so I just used CoRE to fire a maker for home and away mode changes that change the stringify modes. This should be it but I’m sure there are going to be lots of questions with my crappy writing. I apologize in advance cause I’m aware that I’m not the best writer on the planet. Moderators feel free to edit this to be more readable hahaha
The Smartthings Groovy Device Handler Code
/**
* Photon Particle Switch
* |
* By bscuderi Written and modified from Tom Forti's origional code for my specific application Special thanks to him
* TOM FORTI tomforti@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
/**
* Photon Particle Switch
*
*
*/
preferences {
input("token", "text", title: "Access Token")
input("deviceId", "text", title: "Device ID")
}
// for the UI
metadata {
definition (name: "Photon Particle Switch", author: "bscuderi") {
capability "Switch"
}
// tile definitions
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", label: '${name}', action: "switch.off", icon: "st.Electronics.electronics16", backgroundColor: "#79b821"
state "off", label: '${name}', action: "switch.on", icon: "st.Electronics.electronics16", backgroundColor: "#ffffff"
}
main "switch"
details "switch"
}
}
def parse(String description) {
log.error "This device does not support incoming events"
return null
}
def on() {
put '1'
sendEvent(name: 'switch', value: 'on')
}
def off() {
put '0'
sendEvent(name: 'switch', value: 'off')
}
private put(relaystate) {
//Spark Core API Call
httpPost(
uri: "https://api.spark.io/v1/devices/${deviceId}/speakerson",
body: [access_token: token, command: relaystate],
) {response -> log.debug (response.data)}
}
The photon particle code
// Particle Photon Firmware written for a solar and battery powered speaker. The photon sleeps to save power and controls a relay that is accesable via smarthtings or the cloud. The relay turns on and off a Raspoberry PI music server and ampliphier.
// This combination allows the raspberrry pi speaker to be able to be acesable on demand and run off alot smaller battery and solar pannel.
// By Brennon Scuderi
//
//
// set all the variables
//
//
int rpi = D0; // makes pin D0 rpi
// Sets the permenant sleep and wakeup time in seconds
const int secGo2Sleep = 2*3600 + 00*60 + 00;
const int secWakeUp = 9*3600 + 00*60 + 00;
//
//
//runs once upon boot or wake up
//
//
void setup()
{
//Tell the world I'm online
Particle.publish("imup", "on");
// Register and make Particle functions visable to the cloud
Spark.function("speakerson", raspberryon);
Particle.function("goodnight", gnight);
Particle.function("mode", mod);
// Initialize output pins
pinMode(rpi, OUTPUT);
// take control of the LED
RGB.control(true);
// the following sets the RGB LED off:
RGB.color(0, 0, 0);
//set local time = or - from UTC
Time.zone(-7);
}
//
//
// This routine loops forever to see if the device needs to sleep based upon the permenant times set above
//
//
void loop() {
int secNow = Time.local() % 86400; // whats the current second of the day
if (secGo2Sleep <= secNow && secNow < secWakeUp)
{
System.sleep(SLEEP_MODE_DEEP, secWakeUp - secNow);
}
}
//
//
// functions that run only if commanded by the cloud
//
//
// Turns On and Offthe Raspberry PI
int raspberryon(String command)
{
if (command == "1")
{
digitalWrite(rpi, HIGH);
return 1;
}
else
{
digitalWrite(rpi, LOW);
return 0;
}
}
// If I go to bed and run the smartthings goodnight routine this function sleeps the photon a little earlier to save more battery while still waking at the permenant wake time
int gnight(String command)
{
int secnow = Time.local() % 86400; // whats the current second of the day
if (secnow > secWakeUp && command == "goodnight") //runs this time calculation for sleep if goodnight is requested before midnight
{
System.sleep(SLEEP_MODE_DEEP, 86400-secnow+secWakeUp);
return 1;
}
if (secnow < secWakeUp && command == "goodnight") // runs this time calculation for sleep if goodnight is requested after midnight
{
System.sleep(SLEEP_MODE_DEEP, secWakeUp - secnow);
return 1;
}
else
{
return -1;
}
}
// Runs if commanded while away from the house to sleep the photon for 5 minutes after 5 minutes it will wake send a command that its awake to IFTT then if Im still away from the house IFTT calls for this command to sleep it again...
int mod(String command)
{
if (command == "away")
{
System.sleep(SLEEP_MODE_DEEP, 300);
return 1;
}
else
{
return -1;
}
}