-
Westminster Quarters
04/23/2017 at 14:48 • 0 commentsAfter I had changed from python to arduino, I added to the new arduino code the melodies of the Westminster Quarters.
#define GIS D7 #define FIS D6 #define E D5 #define B D2 #define BIGBEN D1 // https://en.wikipedia.org/wiki/Westminster_Quarters void WestminsterFirstQuarter(int speed = 900) { // 1 g♯4, f♯4, e4, b3 dong(GIS); delay(speed); dong(FIS); delay(speed); dong(E); delay(speed); dong(B); delay(speed * 2); } void WestminsterHalfHour(int speed = 900) { // 2 e4, g♯4, f♯4, b3 dong(E); delay(speed); dong(GIS); delay(speed); dong(FIS); delay(speed); dong(B); delay(speed * 2); // 3 e4, f♯4, g♯4, e4 dong(E); delay(speed); dong(FIS); delay(speed); dong(GIS); delay(speed); dong(E); delay(speed * 2); } void WestminsterThirdQuarter(int speed = 900) { // 4 g♯4, e4, f♯4, b3 dong(GIS); delay(speed); dong(E); delay(speed); dong(FIS); delay(speed); dong(B); delay(speed * 2); // 5 b3, f♯4, g♯4, e4 dong(B); delay(speed); dong(FIS); delay(speed); dong(GIS); delay(speed); dong(E); delay(speed * 2); WestminsterFirstQuarter(speed); } void WestminsterFullHour(int hour = 0, int speed = 900) { WestminsterHalfHour(); // 4 g♯4, e4, f♯4, b3 dong(GIS); delay(speed); dong(E); delay(speed); dong(FIS); delay(speed); dong(B); delay(speed * 2); // 5 b3, f♯4, g♯4, e4 dong(B); delay(speed); dong(FIS); delay(speed); dong(GIS); delay(speed); dong(E); delay(speed * 2); for (int i = 0; i < hour; i++) { dong(BIGBEN); delay(speed * 4); } }
-
From RaspberryPi (Python) to NodeMCU (Arduino)
04/16/2017 at 18:36 • 0 commentsAfter changing Balambér's system I also made the new version of this project. The new version of this clock works with NodeMcu ESP8266 V3 WIFI Internet Development Board.
The Raspberry Pi worked well, but I prefer this smaller, more stable Arduino compatible wifi module. So the new hardware asks for new software. (I already know that I can use Python with NodeMCU, but I have no idea how. I need to make some research.)
Hardware
The circuit remained the same. But the five pins of the five MOSFET's has to be connected to the nodeMCU's following pins: D1, D2, D5, D6, D7. (We cannot use the following pins: D0 = USER ,D3 = FLASH, D4 = TXD1 . If we use them we cannot reset and/or update firmware without disconnecting the NodeMCU from the circuit.)
Software
The new software is written in the Arduino IDE. You can find the code here.- The serial_test code helps to debug the project. You can send command through the serial port. Like: "B1 T0.05" = Hit the FIRST Bell/Rod with 50 ms. The value of T is important, because adjusting that number you can make the hammer hits sound equally.
- The webCmd is an ugly-written small library. That helps to build the mini-website for the project. (The serial_test does not need this library.)
- The main file is the Audible_notifications_by_a_Grandfather_s_clock . Be aware of the 7th line where you can adjust the hit-time of the rods (BigBen, 1, 2, 3, 4).
This software is in a very early stage. It cannot play melodies. Yet. I will work on it.
-
New mechanics - advise needed
04/16/2017 at 13:47 • 0 commentsI had to dismount the clock when I moved home to Europe. And when I rebuilt the project I encountered with a significant difficulty. The five solenoids needs significantly different power to move the hammers. It is because of the different home-made springs, and length of the lines, etc. (You can hear this difference even in the original video. ) This has became a huge problem.
What can I do? Here are my possible solutions:
a) Feed the solenoids much more power and with adjustable resistors I can adjust the power of the overpowered solenoids. (It needs new circuit board. And the solenoids are overpowered already.)
b) Feed the solenoids much more power and I can adjust the power with the adjustment of hammer-time in the software (10-400 ms). (It needs more complex software design. But this adjustment has limited effect. This cannot resolve the entire problem.)
c) Make new springs. (It is not easy to make springs with equal strength. And this alone is not a solution, even though it can help significantly.)
d) Let's change the springs and use small weights like lead. (I do not have adjustable small weights. And does it really work?)
What should I do? Do you have any suggestion?
-
Software Update
05/18/2016 at 00:53 • 0 commentsThe recent Python code can be found in the Github repository. After the code v0.2, I cleaned out the code. I made a new mChimes.py file which is imported from all the other files. The main static settings are in this file as well. As a result all the other files became very short. Enjoy.
chimeClock.py:
import datetime, sys, zmq import mChimes as chimes speed = 0.8 firstQuarter = "1:%(speed)s-2:%(speed)s-3:%(speed)s-4:%(doubleSpeed)s" % {"speed": speed, "doubleSpeed": speed * 2} secondQuarter = "3:%(speed)s-1:%(speed)s-2:%(speed)s-4:%(doubleSpeed)s-3:%(speed)s-2:%(speed)s-2:%(speed)s-3:%(doubleSpeed)s" % {"speed": speed, "doubleSpeed": speed * 2} thirdQuarter = "1:%(speed)s-3:%(speed)s-2:%(speed)s-4:%(doubleSpeed)s-4:%(speed)s-2:%(speed)s-1:%(speed)s-3:%(doubleSpeed)s-1:%(speed)s-2:%(speed)s-3:%(speed)s-4:%(doubleSpeed)s" % {"speed": speed, "doubleSpeed": speed * 2} fourthQuarter = "3:%(speed)s-1:%(speed)s-2:%(speed)s-4:%(doubleSpeed)s-3:%(speed)s-2:%(speed)s-1:%(speed)s-3:%(doubleSpeed)s-1:%(speed)s-3:%(speed)s-2:%(speed)s-4:%(doubleSpeed)s-4:%(speed)s-2:%(speed)s-1:%(speed)s-3:%(doubleSpeed)s" % {"speed": speed, "doubleSpeed": speed * 2} Hour = "0:%(speed)s"% {"speed": speed * 4} now=datetime.datetime.now() if now.minute == 15: chimes.sound(firstQuarter) elif now.minute == 30: chimes.sound(secondQuarter) elif now.minute == 45: chimes.sound(thirdQuarter) elif now.minute == 0: if(now.hour > 12): hour = now.hour - 11 elif(now.hour == 0 ): hour = 12 else: hour = now.hour chimes.sound(fourthQuarter+'-%s' % '-'.join(str(Hour) for x in xrange(1,hour)))
-
Reset Button
05/14/2016 at 21:27 • 0 commentsThe RPi sometimes loses its internet-connection, and I need to reset to RPi in a safe way. So I added a small GPIO input push button:
Some of the GPIO-s of the RPi has built in pull-up or pull-down, so I did not use external pull-up/down circuit. I put the button to HeaderPin 7 (GPIO 4) and HeaderPin 9 (GND) and I use a simple code with a special part for the GPIO.setup:
import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BOARD) GPIO.setup(7, GPIO.IN, pull_up_down=GPIO.PUD_UP) while True: input_state = GPIO.input(7) if input_state == False: print('Button Pressed') time.sleep(0.2)
Another advantage of this item that I can use it with both male and female head, and my GND pin remains accessible for other jumper wires. -
How to fry your Pi
04/22/2016 at 15:24 • 0 commentsHave you seen my first Circuit? Well, I'm a beginner and I've made a very amateur mistake. Have you known that it was not a good idea to connect a GPIO out to the GND without any consumer? Well a MOSFET is not a consumer.
I connected my GPIO to the MOSFET. I measured the running current, and it was 35mA. I thought it is not a lot and it should be fine. So I short (is this the right word?) my GPIOs even though for only a very short moment (0.01 sec) at a time. What has happened? I noticed nothing. It worked well, and the notifications system made beautiful sounds. But later I run into a problem: the Pi was not working as expected. There were more and more error messages. About corrupted files. I had to recreate my whole system.
So shorting your GPIOs for a very short time does not necessarily kills the Pi, but destroys your system step by step. One easy solution is to put a 330 Ohm resistor between the MOSFET and the Pi.
-
Clock Add-On
04/21/2016 at 01:03 • 0 commentsThis notification project can work as a normal grandfather's clock with famous Westminster Quarters melody. The easiest way is to use this Add-On file called chimeClock.py. You can invoke it regularly adding this line to your crontab (crontab -e):
0,15,30,45 * * * * python /path/to/file/chimeClock.py
Attention! This chimeClock.py works only if the chimeService.py is running, as it is written in the Program Code v0.2.chimeClock.py
import datetime import sys, zmq speed = 0.8 #Mute it during night hours now=datetime.datetime.now() if ( ( now.hour > 22 ) and ( now.minute > 10 ) ) or ( now.hour < 9 ): sys.exit(0) port = "5555" #Westminster Quarters firstQuarter = [1,speed,2,speed,3,speed,4,speed * 2] secondQuarter = [3,speed,1,speed,2,speed,4,speed * 2, 3,speed,2,speed,1,speed,3,speed * 2] thirdQuarter = [1,speed,3,speed,2,speed,4,speed * 2, 4,speed,2,speed,1,speed,3,speed * 2, 1,speed,2,speed,3,speed,4,speed * 2] fourthQuarter = [3,speed,1,speed,2,speed,4,speed * 2, 3,speed,2,speed,1,speed,3,speed * 2, 1,speed,3,speed,2,speed,4,speed * 2, 4,speed,2,speed,1,speed,3,speed * 2] Hour = [0,speed * 4] context = zmq.Context() socket = context.socket(zmq.REQ) socket.connect ("tcp://localhost:%s" % port) def preparePattern( array ): pattern = "" for i in range(0, len(array), 2): pattern = pattern + str(array[i]) + ":" + str(array[i+1]) if i < len(array) - 2 : pattern = pattern + "-" return pattern def sound( array ): pattern = preparePattern(array) socket.send (pattern) if now.minute == 15: sound(firstQuarter) elif now.minute == 30: sound(secondQuarter) elif now.minute == 45: sound(thirdQuarter) elif now.minute == 0: sound(fourthQuarter) if(now.hour > 12): hour = now.hour - 11 elif(now.hour == 0 ): hour = 12 else: hour = now.hour for x in xrange(1,hour): sound(Hour) pass
-
Program Code v0.2
04/20/2016 at 04:11 • 0 commentsAfter the Program Code v0.1, I made a better but still simple code. There is no need for wsgi module anymore. But there is need of zmq module. See the new Preparing the Raspberry Pi.
The new system works with three files. The chimeService.py runs continuously and it is waiting for calling on port 5555. The chimeClient.py can send a request for pattern to the service. This python file can be called from cron, from other scripts, etc. The chimes.php is the file on the webserver. It can call the chimeClient when that is needed.
- You can send a pattern to make music. For example http://your_ip_address/chimes.php?pattern=1:0.5-1:0.5-4:1. That means: hit the rod 1, then wait 0.5 sec, then hit the rod 1, then wait 0.5 sec, then hit the rod 4, then wait 1 sec.
- You can use the IFTTT's Maker channel to make a specific chime web request. So the chimes can be triggered when you receive in important email, or you wife comes home, or there is a new instagram photo, etc. etc.
chimeService.py
import sys, zmq import RPi.GPIO as GPIO import time, datetime, re port = "5555" GPIO.setmode(GPIO.BOARD) #Connect the RodNumbers to the GPIO board numbers. chimeRod2Pin = {0: 37, 1: 36, 2: 33, 3: 31, 4: 29} GPIO.setwarnings(False) for pin in chimeRod2Pin: GPIO.setup(chimeRod2Pin[pin], GPIO.OUT,initial=GPIO.LOW) context = zmq.Context() socket = context.socket(zmq.REP) socket.bind("tcp://*:%s" % port) power = float def calculatePower(): power = 0.06 now = datetime.datetime.now() if ( now.hour > 21 ) or (now.hour < 9 ): power = 0.03 else: power = 0.05 return power def hitRod( number ): GPIO.output(chimeRod2Pin[number], GPIO.HIGH) time.sleep(power) GPIO.output(chimeRod2Pin[number], GPIO.LOW) def hitPattern( pattern ): hit = map(str, pattern.split('-')) for i in range(0, len(hit)): if hit[i] != '': tmp = map(float, hit[i].split(':')) hitRod(tmp[0]) time.sleep(tmp[1]) def validatePattern( subject ): pattern = "^([0-4]{1}:\d{1}(\.\d{1,2}|)(-|$))+$" matchObj = re.match(pattern, subject) if not matchObj: return False else: return True while True: # Wait for next request from client message = socket.recv() print "Received request: ", message, if not validatePattern(message): print "=> Invalid pattern!!" socket.send("Invalid pattern!") else: power = calculatePower() hitPattern(message) print "=> Done." socket.send("Done.")
chimeClient.py
import sys, zmq port = "5555" context = zmq.Context() print "Connecting to server..." socket = context.socket(zmq.REQ) socket.connect ("tcp://localhost:%s" % port) if len(sys.argv) > 1: pattern = sys.argv[1] print "Sending pattern: ", pattern socket.send (pattern) message = socket.recv() print "Received reply: ", message
chimes.php
<strong>Let's make some noise!</strong><br/><br/> Please send the request pattern in the url.<br/> See for example: <i>?pattern=4:0.5-3:0.5-2:0.5-1:0.5-0:1-0:1</i><br/><br/> <?php $pattern = $_REQUEST['pattern']; if(!validatePattern($pattern)) { echo "<strong>Invalid pattern! Please see the example.</strong>"; exit; } echo "<strong>Current request:</strong> ".$pattern; /* Run the pattern without waiting for response */ exec('python /path/to/file/chimeClient.py "'. $pattern .'" > /dev/null 2>/dev/null &'); /* Run the pattern and wait for the response exec('python /path/to/file/chimeClient.py "'. $pattern .'" ',$output,$return); echo "<pre>"; foreach($output as $line) echo $line."\n"; echo "</pre>"; */ function validatePattern($pattern) { if(preg_match('/^([0-4]{1}:\d{1}(\.\d{1,2}|)(-|$))+$/', $pattern)) return true; else return false; } ?>
Important notes:
- The GPIO access needs superuser role (sudo). So the chimeService should run by the root. Or another possible solution is to add a chime runner user to the group pi as described here. (Or to add this chime runner user to the root group.) (The chimeClient does not need special access.)
Development for the future:
- The webpage could send the request with ajax so it could receive the answer.
- Anybody can make me crazy if he knows my public ip.
- It cannot hit more than one rod in the same time.
- API for switch off/on? It can be useful for an afternoon nap.
Do you have any other comment, idea, suggestion?