Skip to content
Permalink
Browse files

First Arduino: show score and play sound

  • Loading branch information...
andreasschmidtjensen committed Mar 30, 2019
1 parent 65f1f54 commit c4e473cad15ae9f2042cf38acf0c8935a5c163a0
@@ -0,0 +1,37 @@
#include <LiquidCrystal.h>
#include "pitches.h"

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

void setup() {
Serial.begin(9600);
lcd.begin(16, 2); // init cols and rows
lcd.print("init");
}

void loop() {
if (Serial.available()) {
delay(100);

// first char declares what we receive
char c = Serial.read();
if (c == 'S') { // SOUND
c = Serial.read();

int t = NOTE_A5; // DEFAULT (HOME)
if (c == 'A') t = NOTE_C5; // AWAY

tone(2, t, 500);
} else if (c == 'D') { // DISPLAY
lcd.clear();
while (Serial.available() > 0) {
c = Serial.read();
if (c == '\n') {
lcd.setCursor(0, 1); // first col, second line
} else {
lcd.write(c);
}
}
}
}
}
@@ -0,0 +1,12 @@
import serial
import time

s = serial.Serial("COM3", 9600) # port is COM3, and baud rate is 9600
time.sleep(2) # wait for the Serial to initialize
s.write(b'Ready...')
while True:
text = input('Enter text: ')
text = text.strip()
if text == 'exit':
break
s.write(bytes(text, "utf8"))
Binary file not shown.
@@ -4,4 +4,5 @@ numpy
scikit-learn
imutils
scikit-image
flask
flask
pySerial
@@ -48,7 +48,9 @@ def stats():
source_type = 'webcam'
path = 0

controller = Controller(source_type, path, debug=True)
controller = Controller(source_type, path,
arduino_config={"port": "COM3", "features": ["display", "sound"]},
debug=True)
controller.start()

atexit.register(lambda: controller.stop())
@@ -0,0 +1,47 @@
import serial
import time

DISPLAY = 'D'
SOUND = 'S'


class ArduinoConnector:
def __init__(self, port, config, baud_rate=9600):
self.serial = serial.Serial(port, baud_rate)
self.config = config

self.last_call = time.time()

def has_feature(self, feature):
return "features" in self.config and feature in self.config["features"]

def print_score(self, home, away):
"""
Write D{current scores} to the serial port to show current scores on LCD
:param home:
:param away:
:return:
"""

# make sure to only write to the LCD every few seconds,
# otherwise the LCD will mix up the received text
now = time.time()
if now - self.last_call < 2:
return

self.last_call = now

score_text = f"HOME AWAY\n {home} -- {away}"
self.write(DISPLAY, score_text)

def goal_scored(self, result):
"""
Write S{TEAM} to the serial port to play a sound when a goal is scored, e.g. SA, when Away team scores.
:param result:
:return:
"""
team = "H" if result["team"] == 0 else "A"
self.write(SOUND, team)

def write(self, write_type, content=""):
self.serial.write(bytes(f"{write_type}{content}", "utf8"))
@@ -0,0 +1,20 @@
class Broadcaster:
def __init__(self):
self.onChange = EventHook()


class EventHook(object):
def __init__(self):
self.__handlers = []

def __iadd__(self, handler):
self.__handlers.append(handler)
return self

def __isub__(self, handler):
self.__handlers.remove(handler)
return self

def fire(self, *args, **keywargs):
for handler in self.__handlers:
handler(*args, **keywargs)
@@ -5,6 +5,7 @@
from imutils.video import WebcamVideoStream, FPS
import numpy as np

from tablesoccer.ArduinoConnector import ArduinoConnector
from tablesoccer.SoccerField import SoccerField
from tablesoccer import Detector
from util.camera import get_image
@@ -14,14 +15,22 @@


class Controller(Thread):
def __init__(self, source_type, path, debug=False):
def __init__(self, source_type, path, arduino_config={}, debug=False):
super(Controller, self).__init__()

self.fps = FPS().start()

self.field = SoccerField(YOLO_SIZE, debug)

self.detector = Detector()

self.arduino = None
if "port" in arduino_config:
self.arduino = ArduinoConnector(arduino_config["port"], arduino_config)

if self.arduino.has_feature("sound"):
self.field.goal_broadcast.onChange += self.arduino.goal_scored

self.debug = debug

if source_type == 'webcam':
@@ -78,6 +87,9 @@ def run(self):
env = self.field.draw(env)
self.snapshots["ENVIRONMENT"] = env

if self.arduino.has_feature("display"):
self.arduino.print_score(*self.field.get_score())

def schedule_recalculation(self):
self.recalculate = True

@@ -3,6 +3,7 @@

from tablesoccer.Ball import Ball
import tablesoccer.Players as Players
from tablesoccer.Broadcaster import Broadcaster
from tablesoccer.GoalChecker import GoalChecker


@@ -21,6 +22,8 @@ def __init__(self, field_shape, debug=False):

self.debug = debug

self.goal_broadcast = Broadcaster()

def update(self, detector):
self.center = detector.center
self.corners = detector.corners
@@ -114,5 +117,13 @@ def draw(self, canvas):

return np.array(im)

def get_score(self):
score = [0, 0]
for goal in self.score:
score[goal["team"]] += 1

return score[0], score[1]

def goal_scored(self, result):
self.score.append(result)
self.goal_broadcast.onChange.fire(result)

0 comments on commit c4e473c

Please sign in to comment.
You can’t perform that action at this time.