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()