I couldn't fit the code into the original merry boxes and LED's If you want to see the original blog ckick here -> Automatic christmas bell ringers.
The Arduino code.
#include <Servo.h>
/*********************************************************************
* Messages will all begin with Capital S
* Second byte will be board address
* Third byte will be servo address
*/
#define STX 'S' // Define the Ascii code for start of transmission
unsigned char Byte_In;
unsigned char Board = '1';
//unsigned char chan;
Servo Sv[6]; // Define number of servos
enum Comms_States{WAIT, REC_BOARD, REC_CHANNEL, REC_COMMAND};
enum Comms_States Comms_State;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
Comms_State = WAIT;
Sv[0].attach(3); //Connect servo to port 3
Sv[0].write(90);
Sv[1].attach(5); //Connect servo to port 5
Sv[1].write(90);
Sv[2].attach(6); //Connect servo to port 6
Sv[2].write(90);
Sv[3].attach(9); //Connect servo to port 9
Sv[3].write(90);
Sv[4].attach(10); //Connect servo to port 6
Sv[4].write(90);
Sv[5].attach(11); //Connect servo to port 9
Sv[5].write(90);
}
void loop() {
// put your main code here, to run repeatedly:
// All I'm doing for now is reading the serial port
Read_Serial();
}
void Read_Serial(void) {
if (Serial.available() > 0) {
// read byte
Byte_In = Serial.read();
// digitalWrite(LED_BUILTIN, HIGH);
// delay(100);
// digitalWrite(LED_BUILTIN, LOW);
//delay(100);
switch (Comms_State)
{
case WAIT:
if (Byte_In == 'S')
{
Comms_State = REC_BOARD;
if(digitalRead(LED_BUILTIN) == LOW)
digitalWrite(LED_BUILTIN, HIGH);
else
digitalWrite(LED_BUILTIN, LOW);
}
break;
case REC_BOARD:
if (Byte_In == Board)
Comms_State = REC_CHANNEL;
else
Comms_State = WAIT;
break;
case REC_CHANNEL:
if (Byte_In == '1') {
Sv[0].write(0);
delay(100);
Sv[0].write(90);
}
if (Byte_In == '2') {
Sv[1].write(180);
delay(100);
Sv[1].write(90);
}
if (Byte_In == '3') {
Sv[2].write(0);
delay(100);
Sv[2].write(90);
}
if (Byte_In == '4') {
Sv[3].write(180);
delay(100);
Sv[3].write(90);
}
if (Byte_In == '5') {
Sv[4].write(0);
delay(100);
Sv[4].write(90);
}
if (Byte_In == '6') {
Sv[5].write(180);
delay(100);
Sv[5].write(90);
}
Comms_State = WAIT;
break;
default:
Comms_State = WAIT;
break;
}
}
}
The Python code running on Win 10 using python 3.6
from datetime import datetime
from datetime import timedelta
import winsound
import serial
RS232 = serial.Serial('com5', 9600, timeout = 2)
# Set the frequency for each bell for testing
freq=[0, 1047, 1175, 1319, 1397, 1568, 1760, 1976, 2093]
start_time = datetime.now()
bpm = 110
time = [1,1,2,3,1,2,3,1,2,3,4,1,1,2,3,4,1,2,3,4,1,2,3,4,1,3,1,2,3,1,2,3,1,2,3,4,1,1,2,3,4,1,2,3,4,1,2,3,4,1,1,1,1,2,3,4,1,2,3,1,2,3,4,1,2,3,1,2,3,4,1,2,3,1,2,3,4,1,2,3,1,2,3,4,1,2,3,1,2,3,4,1,2,3,1,4]
bell = [1,3,3,3,3,3,3,3,5,1,2,3,4,4,4,4,4,3,3,3,3,2,2,3,2,5,3,3,3,3,3,3,3,5,1,2,3,4,4,4,4,4,3,3,3,5,5,4,2,1,8,8,1,1,5,5,6,6,5,4,4,3,3,2,2,1,5,5,4,4,3,3,2,5,5,4,4,3,3,2,1,1,5,5,6,6,5,4,4,3,3,2,2,1,8,1000]
board = [1,1,1,1,1,1,3,4,4]
channel = [3,6,1,4,2,5,1,2]
# Calculate the milliseconds
def millis():
dt = datetime.now() - start_time
ms = dt.seconds * 1000 + dt.microseconds /1000
return ms
# Play a beep on PC to help with setting up the tunes
def Play_Bell(b):
winsound.Beep(freq[b],75)
return
# Send commands out to the serial port
def Send_Command(b):
print ("servo",board[b-1],channel[b-1])
RS232.write(b'S%d%d' %(board[b-1],channel[b-1]))
return
# Main Program
# Work out how many miliseconds in a quarter bar
Quarter = 60/bpm*1000
#Set up variables
i=0
count = 1
old = -1
# as long as there is a valid bell number in the table play it. If not quit
while bell[i]<9:
beat = millis()
# If a beat (Quarter of a bar has passed see if a bell needs to play)
if beat > old:
print (beat)
if time[i] == count:
Play_Bell(bell[i])
Send_Command(bell[i])
i=i+1
count = count+1
if count == 5:
count = 1
old += Quarter
# Release the RS232 port
RS232.close()