Hacked artificial outdoor Shouting Rock, controlled by Home Assistant MQTT automation.
Things used in this project
Hardware components
Software apps and online services
Onshape
Lightburn
Hand tools and fabrication machines
Ortur Laser Master 3
Story
Intro and Inspiration
In the prophecy of Chavakuk (Habakkuk) Chapter 2 verse 11, it is written:
“For a stone shall cry from the wall, and a chip shall answer it from a beam.”
This prophecy depicts the state of physical matter during the time of redemption, as also prophesied by Isaiah in Chapter 40 verse 5:
"And the glory of the Lord shall be revealed, and all flesh together shall see that the mouth of the Lord spoke."
As explained in Chabad Legacy, these prophecies indicate that the revelation of the Almighty will be revealed in both the earth and the flesh. The arrival of the Messiah and the revelation of the reality of the Almighty is the purpose and focus of this time.
Inspired by these verses, I created the "A stone from a wall that calls out" representation. I used a hollow artificial rock from Amazon (My focus was not Stone crafting) as the main material and replaced the 10W speaker with a smaller Adafruit 3W speaker connected to a Seeed Studio XIAO ESP32C3 processor and a DFRobot DFPlayer mini audio controller. The Amazon Ring bell detects when I approach the front door, and the Home Assistant smart home system triggers via MQTT the play of the verse "For a stone shall cry out from the wall..." only during the hours between 8am and 8pm, excluding Saturdays and holidays.
This representation makes me feel as if I am living in redemption, even for just a moment. May we all soon attain true and complete redemption in our lifetimes.
Demo
Video Link (The verse saying in Hebrew)
System Drawing
Rock Speaker Hacking
As previously mentioned, my focus was on the electronics and software aspect of the project. For this reason, I purchased a premade stone from Amazon (*). The only challenge was that the stone came with a 10W speaker, which was too powerful and not suitable for the project.
The artificial shallow Rock I purchased
Instead, I used an Adafruit 3W speaker (*) which had a smaller diameter. To accommodate this, I designed a 3mm MDF adapter (**).
* details in the components section above.
** See DXF file of the design in the components section above.
Small Speaker Adaptor
Laser cutting of the Adaptor
Small Speaker located on the Adaptor
Fixed into the Rock
Electronics before Assembly
Speaker with the electronics
Bottom sealing
HomeAsistant Setup
There's not much to say here. It's quite straightforward. I simply ensure that the automation does not run late at night or during holidays. The integration of the Jewish calendar is particularly helpful for this purpose. The front door motion sensor is part of the Amazon ring integration.
Automation Flow
Power Source
Currently, I am using a simple USB battery pack for power. However, I have a small solar panel and lithium battery set equipped with a 3.x to 5V buck converter that I plan to integrate into the project in the future. Something like this.
Final Thoughts
One might question the combination of spirituality and technology, but that's simply who I am. I am eager to connect, share, and discuss with others who share similar perspectives.
Custom parts and enclosures
Speaker Holder
Adaptor to small speaker dxf file
Speaker Holder Drawing
Schematics
Shouting Rock Speaker
Shouting Rock Speaker schematics
Shouting Rock Wiring
Shouting Rock Fritzing Breadboard Wiring
Shouting Rock Schematics
Shouting Rock Fritzing Schematics
Code
Shouting Rock Arduino Sketch
C/C++
Arduino ino file
/***************************************************
DFPlayer - A Mini MP3 Player For Arduino
<https://www.dfrobot.com/index.php?route=product/product&product_id=1121>
***************************************************
This example is based on the function of library for DFPlayer by
[Angelo qiao]([email protected])
GNU Lesser General Public License.
See <http://www.gnu.org/licenses></http:> for details.
All above must be included in any redistribution
****************************************************/
#include "Arduino.h"
#include <HardwareSerial.h>
#include "DFRobotDFPlayerMini.h"
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
#include "WiFi.h"
#define MQTT_SERVER "a.b.c.d"
#define MQTT_SERVERPORT 1883
#define MQTT_USERNAME "XXXXX"
#define MQTT_KEY "YYYYY"
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client *mqtt;
const char* wifi_ssid = "SSID";
const char* wifi_password = "PASS";
/****************************** Feeds ***************************************/
// Setup a feed called 'gps' for subscribing to changes.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
Adafruit_MQTT_Subscribe *body;
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;
//Define two Serial devices mapped to the two internal UARTs
HardwareSerial MySerial0(0);
DFRobotDFPlayerMini myDFPlayer;
char last_str[64]="";
void printDetail(uint8_t type, int value);
void setup()
{
// Configure MySerial0 on pins TX=6 and RX=7 (-1, -1 means use the default)
MySerial0.begin(9600, SERIAL_8N1, -1, -1);
Serial.begin(115200);
Serial.println();
Serial.println(F("DFRobot DFPlayer Mini Demo"));
Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
WiFi.begin(wifi_ssid, wifi_password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
mqtt = new Adafruit_MQTT_Client (&client, MQTT_SERVER, MQTT_SERVERPORT, MQTT_USERNAME, MQTT_USERNAME, MQTT_KEY);
body = new Adafruit_MQTT_Subscribe(mqtt, "/speaking_stone/");
// listen for events on the weather feed
mqtt->subscribe(body);
// connect to MQTT server
mqtt_connect();
if (!myDFPlayer.begin(MySerial0)) { //Use softwareSerial to communicate with mp3.
Serial.println(F("Unable to begin:"));
Serial.println(F("1.Please recheck the connection!"));
Serial.println(F("2.Please insert the SD card!"));
while(true);
}
Serial.println(F("DFPlayer Mini online."));
myDFPlayer.volume(20); //Set volume value. From 0 to 30
}
void loop()
{
Adafruit_MQTT_Subscribe *subscription;
// ping adafruit io a few times to make sure we remain connected
// Serial.println("Ping");
if(! mqtt->ping(3))
{
// reconnect to adafruit io
Serial.println("Reconnect");
if(! mqtt->connected())
{
Serial.println("Connect");
mqtt_connect();
}
}
if (subscription = mqtt->readSubscription(1000))
{
Serial.print(F("GotSomething\n"));
// we only care about the
if (subscription == body)
{
char * orig_str = (char*)body->lastread;
myDFPlayer.play(1);
if (myDFPlayer.available())
{
printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
}
Serial.println(orig_str);
}
}
}
// connect to adafruit io via MQTT
void mqtt_connect() {
int8_t ret;
while ((ret = mqtt->connect()) != 0) {
switch (ret) {
case 1: Serial.println(F("Wrong protocol")); break;
case 2: Serial.println(F("ID rejected")); break;
case 3: Serial.println(F("Server unavail")); break;
case 4: Serial.println(F("Bad user/pass")); break;
case 5: Serial.println(F("Not authed")); break;
case 6: Serial.println(F("Failed to subscribe")); break;
default: Serial.println(F("Connection failed")); break;
}
if(ret >= 0)
mqtt->disconnect();
Serial.println(F("Retrying connection..."));
delay(5000);
}
Serial.println(F("mqtt Connected!"));
}
void printDetail(uint8_t type, int value){
switch (type) {
case TimeOut:
Serial.println(F("Time Out!"));
break;
case WrongStack:
Serial.println(F("Stack Wrong!"));
break;
case DFPlayerCardInserted:
Serial.println(F("Card Inserted!"));
break;
case DFPlayerCardRemoved:
Serial.println(F("Card Removed!"));
break;
case DFPlayerCardOnline:
Serial.println(F("Card Online!"));
break;
case DFPlayerPlayFinished:
Serial.print(F("Number:"));
Serial.print(value);
Serial.println(F(" Play Finished!"));
break;
case DFPlayerError:
Serial.print(F("DFPlayerError:"));
switch (value) {
case Busy:
Serial.println(F("Card not found"));
break;
case Sleeping:
Serial.println(F("Sleeping"));
break;
case SerialWrongStack:
Serial.println(F("Get Wrong Stack"));
break;
case CheckSumNotMatch:
Serial.println(F("Check Sum Not Match"));
break;
case FileIndexOut:
Serial.println(F("File Index Out of Bound"));
break;
case FileMismatch:
Serial.println(F("Cannot Find File"));
break;
case Advertise:
Serial.println(F("In Advertise"));
break;
default:
break;
}
break;
default:
break;
}
}
Home Assistant Automation
YAML
Home Assistant Automation YAML file
alias: speaking_stone
description: ""
trigger:
- type: motion
platform: device
device_id: 9991aecc03c14973b05c8e881b0e574f
entity_id: binary_sensor.front_door_motion
domain: binary_sensor
for:
hours: 0
minutes: 0
seconds: 0
condition:
- condition: state
entity_id: binary_sensor.jewish_calendar_issur_melacha_in_effect
state: "off"
- condition: time
before: "20:00:00"
after: "08:00:00"
action:
- service: mqtt.publish
data:
topic: /speaking_stone/
qos: "0"
payload: play
retain: false
mode: single
The article was first published in hackster, February 6, 2023
cr: https://www.hackster.io/asafmatan/shouting-rock-61d014
author: Asaf Matan