[PYTHON] [Elektronische Arbeit] Ich habe mit Raspberry Pi einen Suica Touch-Sounddetektor hergestellt

Einführung

Vor ungefähr fünf Jahren (ungefähr 2015), als ich mit einem tauben Bekannten zum Abendessen ging ** Manchmal kann ich das Berührungsgeräusch von Suica (der Transport-IC-Karte) nicht hören und mache mir Sorgen, ob ich es berühren könnte ** Ich habe die Geschichte gehört. Zu dieser Zeit wollte ich gerade einen Raspberry Pi in Akihabara kaufen und fragte mich, ob ich etwas dagegen tun könnte. ** Kann ich eine Maschine bauen, die die LED aufleuchtet, wenn ich den Touch-Sound von Suica (PASMO oder ICOCA, was auch immer) aufnehme? ** ** ** Ich dachte darüber nach und versuchte es zu schaffen.

Es ist gut, sich daran zu erinnern, aber da die Ausrüstung (Verkabelung) bereits zerlegt wurde, frage ich mich, wie ich es erklärt habe. Übrigens, obwohl ich mich zum Zeitpunkt des Schreibens dieses Artikels in einer solchen Situation befand, habe ich ihn für weitere zwei Jahre verlassen, bis ich ihn veröffentlicht habe ...

Ausrüstung

  1. Raspberry Pi 1 Model B +: Was ich damals gekauft habe, war Version 1. Ich werde es später schreiben, aber es war schwierig in Bezug auf die Leistung. Jetzt liegt es an Razpai 4, aber ...
  2. Desktop-Mikrofon (MS-STM55): Ein vorhandenes Mikrofon, das ich vor langer Zeit gekauft habe. Verbinden Sie sich mit RPi und geben Sie den Sound ein. In Anbetracht des praktischen Gebrauchs kann so etwas wie ein Stiftmikrofon besser sein.
  3. USB-Audiokonverter (BSHSAU01BK): Als ich ihn an den 3,5-Zoll-RPi-Stecker anschloss, gab es natürlich Rauschen und ich konnte nicht gut aufnehmen. Ich frage mich also, ob ich mich für eine Verbindung über USB entschieden habe.
  4. USB-Mobilbatterie (Anker Astro Mini): Ich habe versucht, die Leistung von RPi aus Gründen der Mobilität aus der Mobilbatterie zu ziehen. Es ist eine Batterie, die nur 1A ausgeben kann, aber es hat gut funktioniert. 5.7 Seg-LED (OSL40562-IR): Ein Teil, das in der Platine steckt und 0 anzeigt. Ein Typ, der Zahlen von 0 bis 9 anzeigen kann. Der Grund, warum es nicht nur eine LED ist, ist, dass ich anzeigen wollte, wie oft der Touch-Sound gehört wurde.
  5. Anschlusskabel oder Universalplatine: Ideal für Experimente, da sie leicht eingesetzt und entfernt werden kann.
  6. LAN-Kabel: Dient zur Eingabe von Befehlen von einem PC über SSH. Wenn Sie das Erkennungsprogramm so einstellen, dass es als Dienst gestartet wird, sollte es ohne PC funktionieren, sodass Sie kein LAN-Kabel benötigen (obwohl ich es nicht ausprobiert habe). Wi-Fi ist jetzt in Raspeye installiert, daher ist dies auch ein Trend der Zeit.

In der Abbildung oben ist auch ein USB-Strom- / Spannungsprüfer angeschlossen. Ich denke, dies war im Standby-Modus (als das Erkennungsprogramm nicht ausgeführt wurde), aber da die USB-Stromversorgung etwa 5 V beträgt, arbeitet sie mit etwa 1,4 W.

Verdrahtung

Wenn Sie sich das Bild der Platine früher genau ansehen, gibt es einen Widerstand, der jedoch den Strom der 7-Segment-LED begrenzt. Mit Blick auf das Datenblatt der 7-Segment-LED,

Also habe ich es über den 220Ω Widerstand, den ich zufällig hatte, mit dem GPIO von RPi verbunden. Informationen zu GPIO finden Sie beispielsweise auf der folgenden Seite. EIN / AUS kann durch Befehle und Programme gesteuert werden.

[^ 1]: Es gibt eine 16-mA-Grenze für den Strom, der durch den GPIO-Pin des Raspberry Pi geleitet werden kann. Daher müssen diese Bedingung sowie die Teile erfüllt sein.

Der GPIO von RPi1 beträgt übrigens 3,3 V. Wenn Sie also einen 220 Ω-Widerstand verwenden, fließt dieser etwa 6 mA zur LED [^ 2]?

[^ 2]: Es gibt eine Grenze für den Gesamtstrom, der durch den GPIO-Pin des Raspberry Pi geleitet werden kann, bis zu 50 mA. In diesem Fall sollte dies jedoch in Ordnung sein, da er 42 mA beträgt, selbst wenn alle 7 Segmente leuchten.

話のネタにするために当時書いていたメモ

Wenn Sie sich ein (beleuchtetes) Segment ansehen, sollten Sie eine solche Schaltung sehen. Tatsächlich scheinen die sieben Segmente parallel geschaltet zu sein, wie das Experiment der Miniaturbirne der Wissenschaft. Es sollte jedoch beachtet werden, dass die + Seite tatsächlich nur im beleuchteten Segment 3,3 V beträgt und das beleuchtete Segment auf der + Seite 0 V beträgt. Das Aus-Segment hat sowohl auf der + als auch auf der Seite 0 V, sodass kein Strom fließt.

Programm

Danach schreiben Sie ein Programm, das auf Python auf Raspbian läuft. Breit geteilt

Sie müssen einen Treffer machen.

Aufnahme vom Mikrofon

Ein über einen USB-Audiokonverter angeschlossenes Mikrofon kann als ALSA-Gerät behandelt werden. Daher habe ich es mit dem Modul alsaaudio geschrieben. Ich wollte auch zum Debuggen aus der WAV-Datei lesen, also habe ich sie so geschrieben, dass beide unterstützt werden.

Eine Sache, die man bei Raspberry Pi beachten sollte, ist, dass das Schreiben eines schlechten Programms schwer ist und nicht geholfen werden kann. Die Verarbeitung, die auf einem PC sofort abgeschlossen werden kann, ist eine schwierige Aufgabe für RPi (insbesondere, wenn Sie wie diese in Echtzeit arbeiten möchten). Während FFT eine feste Anzahl von Bildern (2 Quadrate) verarbeiten muss, kann der Mikrofoneingang nicht immer eine feste Anzahl von Bildern lesen. Aus diesem Grund gibt es einen Prozess wie das Erstellen eines Ringpuffers, das Kombinieren der gelesenen Daten und das Ausschneiden auf eine bestimmte Länge für FFT. Wenn ich es geschrieben hätte, indem ich Listen kombiniert und geschnitten hätte, ohne an irgendetwas zu denken, wäre es zu schwer gewesen, um in Echtzeit zu arbeiten ...

pcmmod.py


# -*- coding: utf-8 -*-
import numpy
import alsaaudio
import wave
import collections

FrameArrayTuple = collections.namedtuple(
    "FrameArrayTuple",
    ["array", "nframes_read"])

# Based on https://scimusing.wordpress.com/2013/10/25/ring-buffers-in-pythonnumpy/
class RingBuffer:
    "A 1D ring buffer using numpy arrays"
    def __init__(self, length):
        pow2 = int(numpy.ceil(numpy.log2(length)))
        self.length = 2 ** pow2
        self.data = numpy.zeros(self.length, dtype='float64')
        self.index_top = 0
        self.index_bottom = 0

    def extend(self, x):
        "adds array x to ring buffer"
        if x.size > 0:
            x_index = (self.index_bottom + numpy.arange(x.size)) & (self.length-1)
            self.data[x_index] = x
            self.index_bottom = x_index[-1] + 1

    def get(self, n=None):
        "Returns the first-in-first-out data in the ring buffer"
        idx = (self.index_top + numpy.arange(min(n, self.count()) if n is not None else self.count())) & (self.length-1)
        self.index_top = idx[-1] + 1
        return self.data[idx]

    def count(self):
        c = (self.index_bottom - self.index_top + self.length) & (self.length-1)
        return c

class PCMInputStream:
    def __init__(self, maxNumFrame):
        #Kann nicht unabhängig instanziiert werden, kann aber vom Vererbungsziel aus aufgerufen werden
        self.maxNumFrame = maxNumFrame
        self.op_array = self.getFramesToArrayOperator()

    def readFrames(self):
        raise NotImplementedError("readFrames() must be implemented")

    def readFrameArray(self):
        frames = self.readFrames()
        return self.op_array(frames)

    def getNumChannels(self):
        raise NotImplementedError("getNumChannels() must be implemented")

    def getFrameRate(self):
        raise NotImplementedError("getFrameRate() must be implemented")

    def getSampleWidthInBytes(self):
        raise NotImplementedError("getSampleWidthInBytes() must be implemented")

    def getFramesToArrayOperator(self):
        sw = self.getSampleWidthInBytes()
        if sw == 1:
            fmt = "uint8"
            shift_amp = 128.0
            max_amp = 128.0
        elif sw == 2:
            fmt = "int16"
            shift_amp = 0.0
            max_amp = 32768.0
        else:
            raise ValueError("getSampleWidthInBytes() must be return 1 or 2")
            return

        return (lambda frames: (numpy.frombuffer(frames, dtype=fmt) - shift_amp) / max_amp)

    def getFrameArrayIterator(self):
        #Versuchen Sie immer, numMaxFrame gleichzeitig zurückzugeben.
        nframes_read = 0
        num_channels = self.getNumChannels()
        arr_buffer = RingBuffer(self.maxNumFrame * 10)
        l = -1
        while l != 0:
            if arr_buffer.count() >= self.maxNumFrame * num_channels:
                nframes_read += self.maxNumFrame
                #In Kanäle teilen
                arr_channels = arr_buffer.get(self.maxNumFrame * num_channels).reshape(self.maxNumFrame, num_channels).T
                yield FrameArrayTuple(arr_channels, nframes_read)
            else:
                arr = self.readFrameArray()
                l = arr.shape[0]
                assert l % num_channels == 0
                #Kombinieren Sie den gelesenen Inhalt
                arr_buffer.extend(arr)

        #Gibt die letzten Daten zurück
        arr = arr_buffer.get()
        nframes_read += arr.shape[0] / num_channels
        arr_channels = arr.reshape(arr.shape[0] / num_channels, num_channels).T
        yield FrameArrayTuple(arr_channels, nframes_read)

    def close(self):
        pass

class PCMInputStreamFromWave(PCMInputStream):
    def __init__(self, filename, maxNumFrame):
        self.wv = wave.open(filename, "r")
        self.ch = self.wv.getnchannels()
        self.rate = self.wv.getframerate()
        self.sw = self.wv.getsampwidth()
        self.maxNumFrame = maxNumFrame
        PCMInputStream.__init__(self, maxNumFrame)

    def readFrames(self):
        return self.wv.readframes(self.maxNumFrame)

    def getNumChannels(self):
        return self.ch

    def getFrameRate(self):
        return self.rate

    def getSampleWidthInBytes(self):
        return self.sw

    def close(self):
        self.wv.close()

class PCMInputStreamFromMic(PCMInputStream):
    def __init__(self, rate, sampleWidth, maxNumFrame):
        self.ch = 1
        self.rate = rate
        self.sw = sampleWidth
        self.maxNumFrame = maxNumFrame

        #Initialisierung des Aufnahmegeräts
        self.pcm = alsaaudio.PCM(alsaaudio.PCM_CAPTURE)
        self.pcm.setchannels(self.ch)
        self.pcm.setrate(self.rate)
        #Lesen Sie zweimal gleichzeitig, um die Verarbeitung zu beschleunigen
        print self.pcm.setperiodsize(self.maxNumFrame * 4)
        if self.sw == 1:
            self.pcm.setformat(alsaaudio.PCM_FORMAT_U8)
        elif self.sw == 2:
            self.pcm.setformat(alsaaudio.PCM_FORMAT_S16_LE)
        else:
            raise ValueError("sampleWidth must be 1 or 2")

        PCMInputStream.__init__(self, maxNumFrame)

    def readFrames(self):
        length, frames = self.pcm.read()
        return frames

    def getNumChannels(self):
        return self.ch

    def getFrameRate(self):
        return self.rate

    def getSampleWidthInBytes(self):
        return self.sw

Berührungsgeräusche erkennen

Dies ist auch eine ziemlich schwierige Erinnerung. Grundsätzlich wurde der Schall durch FFT frequenzanalysiert, und wenn die gegebene Frequenz (des Berührungsschalls) mehr Leistung als die anderen Frequenzen hätte, wäre sie als "berührt" beurteilt worden ... Wenn Sie die for-Schleife jedoch einfach verwenden, als würden Sie ein Programm auf einem PC schreiben, ist sie zu schwer, um in Echtzeit zu arbeiten, wenn Sie beispielsweise die Leistung einer bestimmten Frequenz aus den Komponenten des Frequenzbereichs berechnen (wenn Sie nicht gut darin sind, die Verarbeitung der FFT selbst). Ich erinnere mich, dass ich verschiedene Dinge getan habe, z. B. das Umschreiben der Teile, die mit integrierten Modulen, NumPy und SciPy geschrieben werden können.

suicadetection.py


# -*- coding: utf-8 -*-

import numpy
import scipy.fftpack
import time
import bisect
import collections

DetectionHistoryTuple = collections.namedtuple(
    "DetectionHistoryTuple",
    ["cond_energy", "energy_peak", "freq_center_detected"])

#Konstante, die den Erkennungsstatus darstellt
DETECTION_ON = "on"
DETECTION_OFF = "off"

class SuicaDetection:
    #Frequenzradius der Energieberechnung[Hz]
    FREQ_TOLERANCE = 50
    #Anzahl der gespeicherten Historien
    NUM_HIST_SAVED = 3
    #Energieverhältnisschwelle zum Zeitpunkt der Anstiegsbeurteilung
    THRES_ENERGY_RATIO = 0.25
    #Mindestwert von float64
    EPS_FLOAT64 = numpy.finfo(numpy.float64).eps

    def freq_filter_vector(self, freq_center, freq_tolerance):
        freq_delta = self.freq_axis[1] - self.freq_axis[0]
        # freq_center +/- freq_Die in Toleranz enthaltene Energie
        #Gibt einen zu berechnenden Gewichtsvektor zurück.
        energy_weight = numpy.array(
            [(lambda freq_min, freq_max:
                      (1.0 if freq_min <= f and f + freq_delta <= freq_max
                       else (freq_max - f) / freq_delta if freq_min <= f <= freq_max <= f + freq_delta
                       else (f + freq_delta - freq_min) / freq_delta if f <= freq_min <= f + freq_delta <= freq_max
                       else (freq_tolerance * 2 / freq_delta) if f <= freq_min and freq_max <= f + freq_delta
                       else 0.0))
                 (freq_center - freq_tolerance, freq_center + freq_tolerance)
                 for f in self.freq_axis])
        return energy_weight

    def __init__(self, center_freqs, freq_axis):
        self.ts = time.time()
        self.hist = []
        self.time_axis = []
        self.nframes_read = 0
        self.detected_freq = None
        self.init_energy = None
        self.freq_axis = freq_axis
        #Energiegewicht für die Mittenfrequenz, die Sie erfassen möchten
        self.center_freqs = center_freqs
        self.energy_weight_array = numpy.array([
                self.freq_filter_vector(center_freq, self.FREQ_TOLERANCE)
                for center_freq in center_freqs
            ]).T

    def input_array(self, arr):
        assert len(arr.shape) == 1
        num_frames = arr.shape[0]

        self.detect(arr)

        status = None
        if self.detected_freq:
            #Wenn ein Ton ertönt, ist der Ton dieses Frequenzbandes unmittelbar zuvor dreimal zu hören-Beenden Sie, wenn 5 dB fallen
            if all((t.energy_peak is None) or (t.energy_peak - self.init_energy) < -5 for t in self.hist[-3:]):
                self.detected_freq = None
                status = DETECTION_OFF
        else:
            #Wenn kein Ton zu hören ist, ist es in Ordnung, wenn die Energiebedingung in den letzten drei Fällen zweimal erfüllt ist.
            if len([t for t in self.hist[-3:] if t.cond_energy]) >= 2:
                self.detected_freq = self.hist[-1].freq_center_detected
                self.init_energy = self.hist[-1].energy_peak
                status = DETECTION_ON

        self.nframes_read += num_frames

        return (self.nframes_read, status)
            
    def detect(self, arr):
        #print "start", time.time()
        assert len(arr.shape) == 1
        num_frames = arr.shape[0]

        # FFT
        f = scipy.fftpack.fft(arr)
        e = numpy.square(numpy.absolute(f))
        #Fehlervermeidung
        e = numpy.maximum(e, self.EPS_FLOAT64)

        #Gesamtenergie (konstante Zeiten)
        energy_total = e.sum()
        #Energie für jede Frequenz
        # +/-Kombiniere (verdopple) die Energie der Frequenz von
        energy_axis = 2 * e[0:num_frames/2]
        log_energy_axis = 10 * numpy.log10(energy_axis)

        #Berechnen Sie das Energieverhältnis in der Nähe der angegebenen Frequenz
        energy_weighted = energy_axis.dot(self.energy_weight_array)
        energy_ratio_max, freq_center_detected = \
            max(zip(list(energy_weighted / energy_total), self.center_freqs),
                key=lambda t: t[0])

        #Energiebedingungen
        #Konzentrieren Sie sich auf die stärkste Frequenz
        cond_energy = (energy_ratio_max >= self.THRES_ENERGY_RATIO)

        # +/-Basierend auf der maximalen Leistung innerhalb von 100Hz
        idx_low = bisect.bisect_left(self.freq_axis, freq_center_detected - 100)
        idx_high = bisect.bisect_right(self.freq_axis, freq_center_detected + 100)
        energy_peak = log_energy_axis[idx_low:idx_high+1].max()
        #Zur Geschichte hinzufügen
        self.hist.append(DetectionHistoryTuple(cond_energy=cond_energy,
                                               energy_peak=energy_peak,
                                               freq_center_detected=freq_center_detected))
        #Alte Geschichte löschen
        if len(self.hist) > self.NUM_HIST_SAVED:
            self.hist.pop(0)

Lassen Sie die LED leuchten

Steuern Sie das EIN / AUS des entsprechenden GPIO entsprechend der Nummer, die Sie leuchten möchten. Welches GPIO verwendet werden soll, wird vom aufrufenden Programm festgelegt. Für diese EIN / AUS-Steuerung wurde das Modul RPi.GPIO verwendet.

Es scheint, dass GPIO nur gesteuert werden kann, wenn es als Root ausgeführt wird. Seien Sie also dort vorsichtig.

sevenseg.py


# -*- coding: utf-8 -*-
import sys
import RPi.GPIO as GPIO
import time

class GPIO7seg:
    sevenseg_on = [[0, 2, 3, 5, 6, 7, 8, 9],
                   [0, 1, 2, 3, 4, 7, 8, 9],
                   [0, 1, 3, 4, 5, 6, 7, 8, 9],
                   [0, 2, 3, 5, 6, 8, 9],
                   [0, 2, 6, 8],
                   [0, 4, 5, 6, 8, 9],
                   [2, 3, 4, 5, 6, 8, 9]]

    def __init__(self, id_pin_seg):
        self.id_pin_seg = id_pin_seg
        GPIO.setmode(GPIO.BCM)
        for i in id_pin_seg:
            GPIO.setup(i, GPIO.OUT)

    def digit(self, n):
        for i in xrange(7):
            GPIO.output(self.id_pin_seg[i], n not in self.sevenseg_on[i])

Hauptteil

Beim Aufrufen jedes Moduls aus dem Hauptprogramm leuchtet die LED entsprechend dem Beurteilungsergebnis auf.

Beispielsweise wird 1 angezeigt, wenn ein Piepton ertönt, und 2, wenn ein Piepton ertönt. Beim Passieren des Ticketschalters ist die Bedeutung ein- und zweimal unterschiedlich. Versuchen wir also, sie zu verstehen Es ist ein Programm namens.

Es ist ein GPIO zum Beleuchten einer 7-Segment-LED, aber diesmal entsprechen die Pins 15 bis 21 den Segmenten A bis G (siehe Datenblatt) der 7-Segment-LED.

Wenn Sie dieses Hauptprogramm als Root ausführen (zur GPIO-Steuerung), ändern sich die Zahlen hoffentlich als Reaktion auf den vom Mikrofon aufgenommenen Touch-Sound.

suica_main.py


#!/usr/bin/env python2
# -*- coding: utf-8 -*-

import sys
import numpy
import itertools

import pcmmod
import suicadetection
import sevenseg

# ================================

def main():
    #Signallänge (Anzahl der Abtastwerte)
    MAX_NUM_FRAMES = 512
    #Frequenz, die Sie erkennen möchten
    FREQS_CENTER = [2550, 2700, 3000]

    #Fensterfunktion
    ham_window = numpy.hamming(MAX_NUM_FRAMES)

    #WAVE-Lesung oder Mikrofoneingang
    if len(sys.argv) == 1:
        #Mikrofon
        rate = 44100
        sw = 2
        sound = pcmmod.PCMInputStreamFromMic(rate, sw, MAX_NUM_FRAMES)
    else:
        # WAVE
        sound = pcmmod.PCMInputStreamFromWave(sys.argv[1], MAX_NUM_FRAMES)
        rate = sound.getFrameRate()

    #Frequenzachse
    freq_axis = numpy.fft.fftfreq(MAX_NUM_FRAMES, 1.0/rate)[0:MAX_NUM_FRAMES/2]

    sd = suicadetection.SuicaDetection(FREQS_CENTER, freq_axis)

    #Zähler(7SEG LED)
    counter_ring = 0
    id_pin_seg = [15, 16, 17, 18, 19, 20, 21]
    gpio7 = sevenseg.GPIO7seg(id_pin_seg)
    gpio7.digit(counter_ring)
    #Siehe die zuletzt gezählte Zeit
    counted_last = None

    #Lesen Sie die Wellenform
    #Verwenden Sie bis zum vollständigen und gelesenen Teil
    for arr, nframes_read in itertools.takewhile(lambda t: t.array.shape[1] == MAX_NUM_FRAMES,
                                                 sound.getFrameArrayIterator()):
        #Wird zur Beurteilung verwendet:Nimm L für 2ch
        time_frames, status = sd.input_array(arr[0] * ham_window)
        if status == suicadetection.DETECTION_ON:
            print float(time_frames) / rate, "ON"
            # 0.Zählen Sie nicht, bis 1 Sekunde vergangen ist
            counted_last = time_frames
            pending = True
        elif status == suicadetection.DETECTION_OFF:
            print float(time_frames) / rate, "OFF"
            print
            pending = False

        if counted_last is not None:
            if time_frames > counted_last + rate * 2.0:
                #Setzen Sie die LED nach 2 Sekunden zurück
                gpio7.digit(counter_ring)
                counted_last = None
            elif time_frames > counted_last + rate * 1.0:
                #Keine Combo-Beurteilung nach 1 Sekunde (Zähler nur intern zurücksetzen)
                counter_ring = 0
            elif pending and time_frames > counted_last + rate * 0.1:
                counter_ring += 1
                gpio7.digit(counter_ring)
                pending = False

if __name__ == "__main__":
    main()

Zusammenfassung

Ich glaube, ich habe viele Anpassungen vorgenommen, als ich den Touch-Sound beurteilt habe. Wenn Sie es einfach mit Strom betrachten, reagiert es in einem lauten Bahnhofshof.

Danach stellte sich heraus, dass die Frequenz des Berührungsgeräuschs unerwartet nicht einheitlich zu sein scheint. ** Selbst wenn Sie den Fall des Ticketschalters und den Fall der Kassiererin im Supermarkt vergleichen, ist die Tonhöhe (Frequenz) des Touch-Sounds tatsächlich unterschiedlich **, sodass es immer komplizierter wird, wenn Sie darüber nachdenken, eine Erkennung zu ermöglichen. ….

Übrigens hatte ich mir vorher noch keine Gedanken über die Frequenz des Touch-Sounds gemacht. Als ich dieses Programm schrieb, habe ich zum ersten Mal in Audacity nach bestimmten Zahlen gesucht. Als ich meinem Bekannten zu Beginn berichtete, dass "der Touch-Sound 2550 Hz oder 2700 Hz zu sein scheint", war ich überzeugt, dass "ich ihn nicht hören kann".

Es ist lange her, dass die Leute sagten, es sei barrierefreies oder universelles Design. ** Betrachten Sie nur sichtbare Stufen? Entwerfen Sie den Sound unter Berücksichtigung des Frequenzbandes? ** ** ** Ich glaube, das ist mir aufgefallen. Wenn Sie jedoch den Ton leise machen, kann es aufgrund der Menschenmenge schwierig sein, ihn zu hören. es ist schwierig.

Recommended Posts

[Elektronische Arbeit] Ich habe mit Raspberry Pi einen Suica Touch-Sounddetektor hergestellt
Ich habe einen Ressourcenmonitor für Raspberry Pi mit einer Tabelle erstellt
Ich habe zum ersten Mal eine Überwachungskamera mit Raspberry PI gemacht.
Ich habe mit Razpai einen Webserver erstellt, um Anime zu schauen
Genießen Sie die elektronische Arbeit mit GPIO von Raspberry Pi
[Für Anfänger] Ich habe mit Raspberry Pi einen menschlichen Sensor erstellt und LINE benachrichtigt!
Ich habe mit Python eine Lotterie gemacht.
Ich habe mit Python einen Daemon erstellt
Verwenden einer Webkamera mit Raspberry Pi
Erstellen Sie eine Tensorflow-Umgebung mit Raspberry Pi [2020]
Ich habe mit Python einen Zeichenzähler erstellt
Verbesserter menschlicher Sensor mit Raspberry Pi
Machen Sie einen Waschtrocknungs-Timer mit Raspberry Pi
Ich habe mit Python eine Hex-Map erstellt
Ich habe ein Lebensspiel mit Numpy gemacht
Ich habe einen Hanko-Generator mit GAN gemacht
Bedienen Sie das Oszilloskop mit dem Raspberry Pi
Erstellen Sie eine Auto-Anzeige mit Himbeer-Pi
Ich habe mit Python ein schurkenhaftes Spiel gemacht
Ich habe mit Python einen einfachen Blackjack gemacht
Ich habe mit Python eine Einstellungsdatei erstellt
Ich habe eine WEB-Bewerbung bei Django gemacht
Ich habe mit Python einen Neuronensimulator erstellt
Ich habe versucht, mit Raspeye 4 (Python Edition) ein signalähnliches Signal zu erzeugen.
Ich habe einen Stempelersatzbot mit Linie gemacht
Ich habe mit Python eine Bot-Wettervorhersage gemacht.
Ich habe eine GUI-App mit Python + PyQt5 erstellt
Ich habe versucht, mit Python einen Twitter-Blocker für faule Mädchen zu machen
Ich habe L-Chika mit Razpai 4 (Python Edition) ausprobiert.
[Python] Ich habe mit Tkinter einen Youtube Downloader erstellt.
Ich habe eine einfache Brieftasche aus Bitcoin mit Pycoin gemacht
Ich habe einen LINE Bot mit Serverless Framework erstellt!
Ich habe versucht, mit Raspeye + Tact Switch eine Schaltfläche für Slack zu erstellen
Ich habe mit Numpy eine Grafik mit Zufallszahlen erstellt
Aktieninvestitionsanalyse-App mit Himbeerkuchen gemacht
Ich habe mit Python ein Bin-Picking-Spiel gemacht
Mattermost Bot mit Python gemacht (+ Flask)
Mit Raspberry Pi erstellter Dateifreigabeserver, der für Remote-Arbeiten verwendet werden kann
[AWS] Ich habe BOT mit LINE WORKS daran erinnert
Ich habe einen Twitter BOT mit GAE (Python) gemacht (mit einer Referenz)
Ich habe mit LINE Bot ein Haushaltsbuch für Bot erstellt
Ich habe mit Play with Docker einen gebrauchsfertigen Syslog-Server erstellt
Ich habe mit Python ein Weihnachtsbaum-Beleuchtungsspiel gemacht
Ich habe mit Tkinter ein Fenster für die Protokollausgabe erstellt
Ich habe mit Python eine App für die Benachrichtigung über Netznachrichten erstellt
Ich habe eine Python3-Umgebung unter Ubuntu mit direnv erstellt.
Ich möchte mit einem Roboter in Python arbeiten.
Ich habe versucht, LINE BOT mit Python und Heroku zu machen
Ein Memorandum bei der Herstellung einer Überwachungskamera mit Raspeye
Ich habe mit Sense HAT ein gefallenes Monospiel gemacht
〇✕ Ich habe ein Spiel gemacht
DigitalSignage mit Raspberry Pi
Ich habe versucht, mit OpenCV eine Bewegungserkennungsüberwachungskamera mit einer WEB-Kamera mit Raspberry Pi herzustellen
Eine Geschichte, die stolperte, als ich mit Transformer einen Chat-Chat-Bot erstellte
Ich habe ein einfaches Tippspiel mit tkinter of Python gemacht
Erstellen Sie eine WEB-Überwachungskamera mit Raspberry Pi und OpenCV
Ich habe ein Paket erstellt, um Zeitreihen mit Python zu filtern