I2C Anbindung

  • Wünsche / Anregungen
  • erledigt / gelöst

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

Da in jedem Forum ein paar Regeln eingehalten werden müssen, möchte ich diese auch vorher hier festlegen und niederschreiben. Die grundsätzliche Netiquette setze ich bei Jedem voraus. Darüber hinaus möchte ich nur spezielle Regeln ansprechen:
- Unterlasse FullQuote sondern nutze Alternativen wie Inline-Quoting
-> siehe auch https://de.wikipedia.org/wiki/Fullquote vs. https://de.wikipedia.org/wiki/TOFU#Alternativen_zu_TOFU
- Unterlasse nichtssagende Antworten wie "Danke" oder "werde ich mal testen" oder ähnliches, sofern Du nicht der Threadersteller bist und einen Lösungsvorschlag angeboten bekommen hast.
- Vermeide Doppel-Posts (zwei Beiträge von Dir hintereinander) sondern editiere wenn möglich Deine Posts.

Danke...

  • I2C Anbindung

    Hallo,

    ich hab das im raspi-forum-Thread schon einmal geschrieben, aber dort ist das irgendwie untergegangen.

    Ich möchte neben den coolen features, die doorpi schon bietet, auch eine Matrix-Tastatur anbinden - kostet bei ali unter einem Euro.

    Da der Pi selbst nicht genug Pins hat (wenn man so wie ich auch noch einen RFID-Leser und mehrere Taster angeschlossen hat), habe ich das kurzerhand per Arduino und I2C gelöst.
    Mein Ansatz (da ich mit dem Konzept von doorpi noch nicht so vertraut bin und auch python für mich neu ist):

    Auf dem Raspi läuft parallel zum doorpi ein kleines python-Skript, das die Kommunikation mit dem Arduino übernimmt und mit doorpi über eine einfache File-Schnittstelle kommuniziert (an der config für doorpi muss ich noch feilen, aber nach dem, was ich gelesen habe sollte das funktionieren).

    Da ich nur 5V Relais für den Arduino herumliegen habe und keine Lust hatte, extra zum Elektronik-Shop zu fahren, um mir Sachen zu holen, mit denen ich das Relais am Raspi betreiben kann, habe ich auch das Relais, das dann den Türöffner bedienen soll am Arduino hängen. Das Python-Skript betätigt es, wenn ein bestimmtes File existiert.
    Außerdem wird das Relais von dem Skript betätigt, wenn ein richtiger PIN auf der am Arduino hängenden Tastatur eingegeben wird.
    Ich habe das Skript und den Sketch angehängt - vielleicht kann das mal jemand gebrauchen (und bitte nicht schimpfen, weil mein code stümperhaft ist).

    Nebenbei wäre es toll, wenn I2C ebenfalls (als keyboard?) in doorpi integriert werden könnte - dann würde man sich den Zauber mit eigenem Skript sparen...

    lg

    Pula
    [hr]
    Und hier noch der Sketch (habs leider nicht in einem Posting geschafft, 2 Files hochzuladen)
    Files
    • keypad.zip

      (764 Byte, downloaded 151 times, last: )
    • tastatur_test.zip

      (1.76 kB, downloaded 139 times, last: )

    The post was edited 1 time, last by pula ().

  • RE: I2C Anbindung

    Ganz viele Infos und ich weiß nicht ob ich alles richtig verstanden habe.
    Zum Thema Keypad allgemein - da gibt es auch welche, die mit zwei Pins auskommen:
    http://board.doorpi.org/Thema-50-Beitrag-217-Change_arduino_code_to_use_it_with_raspberry.html#pid217

    Zum Thema DoorPi <-> Arduino - die Anforderung gab es schon einmal:
    https://github.com/motom001/DoorPi/blob/master/doorpi/keyboard/from_usb_plain.py

    Auf Arduino Seite war es der Quellcode:

    Source Code

    1. #define Button 2
    2. #define AudioStrom 3
    3. void setup() {
    4. Serial.begin(9600);
    5. pinMode(Button, INPUT_PULLUP);
    6. pinMode(AudioStrom, OUTPUT);
    7. digitalWrite(AudioStrom, LOW);
    8. }
    9. void loop() {
    10. int Taster = digitalRead(Button);
    11. Serial.println(Taster);
    12. int Strom = Serial.read();
    13. if(Strom == 1){
    14. digitalWrite(AudioStrom, HIGH);
    15. } else if(Strom == 0){
    16. digitalWrite(AudioStrom, LOW);
    17. }
    18. }
    Display All


    Zitat aus der changelog:

    zur Erweiterung der Config:
    Beim Webservice config_save können jetzt auch Platzhalter wie "!BASEPATH!" verwendet werden.

    zum neuen Keyboard:
    Das neue Keyboard wurde gewünscht, damit der DoorPi mit einem Arduino per USB kommunizieren kann.

    Beispiel-Config:
    -------- snip --------
    [keyboards]
    arduino = usb_plain # definiert das neue Keyboard mit Namen und Typ

    [arduino_keyboard]
    port = /dev/ttyUSB0
    baudrate = 9600
    input_stop_flag = \n
    input_max_size = 255 # wieviele Zeichen können max. übertragen werden, bevor es als Müll gilt
    output_stop_flag = \n

    [arduino_InputPins]
    taster = call:**613 # was soll gemacht werden, wenn 'taster' + input_stop_flag über die Leitung kommt?

    [arduino_OutputPins]
    strom_an = AudioStrom an    # strom_an ist der "PinName" und auch gleichzeitig das, was übertragen wird, beim Output (+ output_stop_flag)
    strom_aus ) AudioStrom aus
    -------- snap --------

    Steuern kann man den Output z.B. bei OnStartUp
    -------- snip --------
    [EVENT_OnStartUp]
    10 = sleep:1
    20 = out:strom_an,1

    [EVENT_BeforeShutdown]
    10 = out:strom_aus:1
    -------- snap --------

    Wobei der Wert hinter dem PinNamen vollkommen egal ist. Es wird immer der Name des Pins gesendet.
    In dem Beispiel würde beim Start von DoorPi zuerst strom_an und beim Beenden von doorPi wieder strom_aus gesendet.


    Quelle: http://www.forum-raspberrypi.de/Thread-haussteuerung-doorpi-voip-wechselsprechanlage-tuersprechanlage-mit-video-support?pid=168810#pid168810


    Zu Deiner keypad.py (die dringend eine richtige IDE brauch, da Tabs und Space gemischt sind und das bei Python zu Syntax-Fehler führen kann), schau Dir mal diese Datei an:
    https://github.com/motom001/DoorPi/blob/master/doorpi/keyboard/from_rdm6300.py

    Vom Grundgedanken gleich - warte auf bestimmte Zeichenfolge und öffne dann die Tür. Eventuell kannst Du damit "kurzerhand" ein eigenes Keypad schreiben.
    --
    MfG Thomas

    The post was edited 1 time, last by motom001 ().

  • RE: I2C Anbindung

    Hi!

    Danke für die rasche Antwort!

    Naja - ich bastle hier nur mit vim herum, hab nur Linux und so viel hab ich mit python noch nicht gemacht :(
    Aber danke für den Hinweis - wenn ich wirklich mehr mache, werd ich mich mal umschaun, was es so an IDEs für Linux und Python gibt. Eclipse is ja hier wie mit Kanonen auf Spatzen schießen...

    Wenn ich das richtig verstanden habe, dann ist das keyboard für den arduino einfach eine "einfache" Terminal-Anbindung?

    Ich werde mir das rfid-keyboard genauer ansehen, aber ich kann noch nicht versprechen, daß ich da durchsteige. Richtig programmieren ist bei mir schon eine Weile her und so firm bin ich mit I2C auch nicht (war froh, daß ich das so weit mal hinbekommen habe). Aber eleganter, als mit files zu arbeiten wäre das allemal....


    So richtig spannend ist doorpi meiner Einschätzung auch, wenn man es mit einer Hausautomatisierung (in meinem Fall fhem) koppelt. Ich denke da zb an Dinge wie automatisches Einblenden des Kamera-Bildes ins laufende Fernsehen oder Türöffnen per Fernbedienung (entweder aus fhem oder aus kodi heraus).... spannend, spannend :)
  • RE: I2C Anbindung

    So unterschiedlich sind die Welten - ich kenne mich (zumindest ein wenig) mit Programmierung aus, aber dafür sind FHEM und kodi für mich "böhmische Dörfer"...

    FHEM hab ich mir einmal angesehen und dachte von der Oberfläche: "Willkommen im Jahr 1993"
    Und was der Unterschied zwischen kodi und FHEM ist hab ich bis heute nicht verstanden...

    // EDIT \\

    Hab den Quellcode für den Arduino oben noch ergänzt...
    --
    MfG Thomas

    The post was edited 1 time, last by motom001 ().

  • RE: I2C Anbindung

    Also naja.... kodi ist ein mediaplayer (den ich auch zum Fernsehen einsetze zb) und fhem ist ein Hausautomatisierungs-System, das in perl geschrieben wurde.

    Die Standard-Oberfläche ist vielleicht nicht so jedermanns Sache, aber man kann das mit diversen Mitteln super anpassen.
    Ich steuere zb damit Rolladen, Beleuchtung, Lüfter, Zirkulationspumpe, Multimedia, Fritzbox, Verstärker, Squeezebox-Player (auf einem raspi im Bad), Beschattung, Fenster/Tür Status etc. Ist ziemlich mächtig mittlerweile und das schöne ist, es ist extrem offen für viele, viele verschiedene Systeme (von Homematic über Arduino, mysensors, Beleuchtungs-Protokolle wie Wifilight, Hue und so weiter).
    Ich hab grad umgebaut und hab mir das alles mehr oder weniger selbst gebaut inkl. vollständiger LED-Beleuchtung um unter 2000€ - wenn man so was fertig kauft, ist man in etwa 20.000 € los....
    Und da passt doorpi wunderbar rein - weil man da zb. auch Events absetzen kann. Beispielsweise könnte man bestimmte Beleuchtungen einschalten im Haus, wenn der RFID-Reader einen bestimmten Chip erkennt. Oder eben ein Live-Umschalten des Fernsehers auf das Kamerabild vom doorpi, wenn jemand läutet :)

    Falls Dich das Thema Hausautomatisierung interessiert, schau mal auf forum.fhem.de - da gibts jede Menge Infos und auch viele hilfsbereite Menschen :)

    //EDIT \\
    Und ja: ist eine einfache Terminal-Implementation :)
    [hr]
    Aber noch eine andere Frage:
    Hab grad festgestellt, daß meine kleine python-Routine so den Raspi (Modell A) zu etwa 40% auslastet.
    Wenn ich ein time.sleep(.2) einfüge funktioniert es noch genau so gut (kein Mensch kann so schnell drücken) und lastet das System nicht mehr spürbar aus.
    Da ich die Architektur von doorpi nicht kenne - wenn ich hier ein sleep in das Modul einbauen würde, bremst das doorpi dann aus?
    Muss ich das keyboard dann (außer in der ini) irgendwie speziell einbinden? Oder erkennt doorpi das modul, wenn es im keyboard-dir liegt von selbst?

    The post was edited 1 time, last by pula ().

  • RE: I2C Anbindung

    pula001 wrote:


    Da ich die Architektur von doorpi nicht kenne - wenn ich hier ein sleep in das Modul einbauen würde, bremst das doorpi dann aus?


    Leider ja - deshalb mit threads arbeiten wie beim rdm6300

    pula001 wrote:


    Muss ich das keyboard dann (außer in der ini) irgendwie speziell einbinden? Oder erkennt doorpi das modul, wenn es im keyboard-dir liegt von selbst?


    Du musst nichts spezielles einbinden außer das Keyboard im Dir ablegen - Keyboards werden dynamisch anhand deren Namen nachgeladen, sobald diese in der Config aktiviert werden...
    --
    MfG Thomas
  • RE: I2C Anbindung

    Hi,

    hab mal ein wenig angefangen, aber teilweise seh ich den Wald vor lauter Bäumen nicht, hab ich das Gefühl. Hab zb nicht wirklich Ahnung, was die _ immer bedeuten, aber das lässt sich recherchieren.

    Was ich aber nicht verstehe:
    Im Gegensatz zu dem RFID-Reader habe ich keine definierten Start- und End-Chars. Also müsste ich in der Schleife auf die Strings aus der ini prüfen. Kannst Du mir hier bitte weiterhelfen?
    Hab mal ein wenig angefangen, dein Keyboard ein wenig umzuklempnern (sorry, bin wirklich noch kein Python-Profi)....

    Python Source Code

    1. #!/usr/bin/env python
    2. # -*- coding: utf-8 -*-
    3. #
    4. #  Configuration
    5. #  -------------
    6. #
    7. #  1. Define a new keyboard of type 'i2c'
    8. #  2. Define inputPins section for that keyboard
    9. #
    10. #  Sample:
    11. #
    12. #  [keyboards]
    13. #  i2cconnection = i2c
    14. #  ...
    15. #  [i2connection_InputPins]
    16. #  1234567 = out:Tueroeffner,1,0,3
    17. #  2345678 = out:Tueroeffner,1,0,3
    18. #
    19. #  That's all...
    20. #
    21. #
    22. #
    23. #  Hardware Connections
    24. #  --------------------
    25. #  Connect the I2C Pins of Arduino and Raspberry as follows:
    26. #  SDA (A4 on an UNO) to SCL (GPIO3, Pin 5) on the Raspi
    27. #  SCL (A5 on an UNO) to SDA (GPIO2, Pin 3) on the Raspi
    28. #  GND of Arduino to GND of Raspi
    29. #  see also http://blog.oscarliang.net/raspberry-pi-arduino-connected-i2c/
    30. #  you will also need the smbus-libs for python
    31. #  to install on raspbian simply do a
    32. #  sudo apt-get install python-smbus
    33.  
    34. import logging
    35. logger = logging.getLogger(__name__)
    36. logger.debug("%s loaded", __name__)
    37. import threading
    38. import serial
    39. import time
    40. from doorpi.keyboard.AbstractBaseClass import KeyboardAbstractBaseClass, HIGH_LEVEL, LOW_LEVEL
    41. import doorpi
    42. #otto
    43. import smbus
    44. DELETE_KEY = 'D'
    45. bus = smbus.SMBus(1)
    46. address = 0x04
    47. # otto ende
    48. START_FLAG = '\x02'
    49. STOP_FLAG = '\x03'
    50. MAX_LENGTH = 14
    51. def get(**kwargs): return RDM6300(**kwargs)
    52. class I2C(KeyboardAbstractBaseClass):
    53.     name = 'I2C basic keyboard and relay keyboard'
    54.     @staticmethod
    55.     def readtast():
    56.         try:
    57.             tast = self._bus.read_byte_data(address, 1)
    58.             if (tast >= 48 and tast <= 57) or (tast >= 64 and tast <= 68):
    59.                 #print(tast)
    60.                 return tast
    61.         except IOError:
    62.             time.sleep(.001)
    63.     @staticmethod
    64.     def sendi2c(apin):
    65.         try:
    66.             bus.write_byte(address, apin)
    67.         except IOError:
    68.             time.sleep(.001)
    69.     def readI2C(self):
    70.         self._bus = smbus.SMBUS(1)
    71.         try:
    72.             chars = ""
    73.             while not self._shutdown:
    74.                 # char holen
    75.                 now = time.time()
    76.                 #nach festgelegter zeit puffer leeren
    77.                 if now - self.last_key_time > self.__dismisstime:
    78.                         chars = ""
    79.                 newchar = readI2C.readtast()
    80.                 if newChar != 0 and newChar != None:
    81.                     self.last_key_time = now
    82.                     logger.debug("I2C new char %s read", newChar)
    83.             
    84.                     chars += str(newChar)
    85.                     # aktuelles Ergebnis kontrollieren
    86.                     # hier Vergleich mit PIN aus ini?!  --> wie????
    87.                     if newChar == STOP_FLAG and chars[0] == START_FLAG and len(chars) == MAX_LENGTH and RDM6300.check_checksum(chars):
    88.                         logger.debug("found tag, checking dismisstime")
    89.                         # alles okay... nur noch schauen, ob das nicht eine Erkennungs-Wiederholung ist
    90.                         now = time.time()
    91.                         if now - self.last_key_time > self.__dismisstime:
    92.                             doorpi.DoorPi().event_handler('OnFoundTag', __name__)
    93.                             self.last_key = int(chars[5:-3], 16)
    94.                             self.last_key_time = now
    95.                             logger.debug("key is %s", self.last_key)
    96.                             if self.last_key in self._InputPins:
    97.                                 self._fire_OnKeyDown(self.last_key, __name__)
    98.                                 self._fire_OnKeyPressed(self.last_key, __name__)
    99.                                 self._fire_OnKeyUp(self.last_key, __name__)
    100.                                 doorpi.DoorPi().event_handler('OnFoundKnownTag', __name__)
    101.                             else:
    102.                                 doorpi.DoorPi().event_handler('OnFoundUnknownTag', __name__)
    103.                     # ggf. löschen
    104.                     if newChar == DELETE_KEY:
    105.                         chars = ""
    106.         except Exception as ex:
    107.             logger.exception(ex)
    108.         finally:
    109.             # shutdown the UART
    110.             logger.debug("I2C thread ended")
    111.         
    112.     def __init__(self, input_pins, keyboard_name, conf_pre, conf_post, *args, **kwargs):
    113.         logger.debug("__init__ (input_pins = %s)", input_pins)
    114.         self.keyboard_name = keyboard_name
    115.         self._bus = smbus.SMBUS(1)
    116.         doorpi.DoorPi().event_handler.register_event('OnFoundTag', __name__)
    117.         doorpi.DoorPi().event_handler.register_event('OnFoundUnknownTag', __name__)
    118.         doorpi.DoorPi().event_handler.register_event('OnFoundKnownTag', __name__)
    119.         self.last_key = ""
    120.         self.last_key_time = 0
    121.         # somit wirds aus der Config-Datei geladen, falls dort vorhanden.
    122.         section_name = conf_pre+'keyboard'+conf_post
    123.         self.__dismisstime = doorpi.DoorPi().config.get_int(section_name, 'dismisstime', 20)
    124.         for input_pin in self._InputPins:
    125.             self._register_EVENTS_for_pin(input_pin, __name__)
    126.         self._shutdown = False
    127.         self._thread = threading.Thread(target = self.readI2C)
    128.         self._thread.daemon = True
    129.         self._thread.start()
    130.         self.register_destroy_action()
    131.     def destroy(self):
    132.         if self.is_destroyed: return
    133.         logger.debug("destroy")
    134.         self._shutdown = True
    135.         doorpi.DoorPi().event_handler.unregister_source(__name__, True)
    136.         self.__destroyed = True
    137.     def status_input(self, tag):
    138.         logger.debug("status_input for tag %s", tag)
    139.         if tag == self.last_key:
    140.             return True
    141.         else:
    142.             return False
    143.     def set_output(self, pin, value, log_output = True):
    144.         # noch recherchieren, wie das mit den outputs funktioniert....
    145.         return False
    Display All


    Ach ja... beim I2C kommts immer wieder zu errors, daher die sleep(.001) in den excepts

    Cheers,

    Otto

    The post was edited 1 time, last by pula ().

  • RE: I2C Anbindung

    Ach so - ja, das ist richtig.
    Ich hab das auch oben in dem code vermerkt. Habe aus den raspbian-repos die Pakete

    Source Code

    1. python-smbus python3-smbus pypy-smbus-cffi


    nachinstalliert. Ich habe heute keine Zeit mehr, aber ich kann morgen ausprobieren, ob wirklich alle drei notwendig sind (habe sicherheitshalber alles installiert, was python und smbus war)...

    Python selber kann anscheinend ohne diese libs nicht mit I2C kommunizieren...

    lg
    Pula
    [hr]
    Hi,

    OK, habs getestet.

    Source Code

    1. python-smbus


    reicht aus, damit die Kommunikation funktioniert...
    [hr]
    Was mir aber nicht wirklich weiterhilft...

    kannst du mir bitte kurz sagen, wie ich eine eingabe mit einem eintrag in der ini vergleichen kann?
    ich vermute, es handelt sich um diesen code:

    Source Code

    1. for input_pin in self._InputPins:
    2. if self._last_received_chars.endswith(input_pin):

    aber werd da nicht ganz schlau... :(
    müsste den gesamten eingegebenen pin mit einem in der ini hinterlegten vergleichen....

    The post was edited 1 time, last by pula ().