Ausgabe von Zeile/Spalte nach einlesen von csv

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
cardeto
User
Beiträge: 11
Registriert: Freitag 27. September 2013, 18:44

Hallo zusammen,

da sich meine Kenntnisse nur auf Grundkurs C++ beschränken und ich vor einer Aufgabe stehe die ich im Moment nicht so hin bekomme, frage ich hier um Hilfe.
Ziel:
Ich möchte eine csv Datei einlesen, aus der Zeile 1 die Werte aus Spalte 1 und Spalte 5 ausgeben.Danach Zeile 2 usw.
Das ganze soll später auf einem 2x16 Zeichen LCD am Raspberry ausgegeben werden. Durch Tastdruck wird in die nächste Zeile gesprungen.

Code: Alles auswählen

import csv

x = 0


with open("Test.csv","r", newline="") as csvfile:
    spamreader = csv.reader(csvfile, delimiter=";", quotechar="|")
        
    for col in spamreader:
        for row in spamreader:
            x = x+1
            input ("Drücken Sie Eingabe")# Hier soll später der Tastendruck kommen
            print (x,row[0])
            print (row[4])
Da ich bei Stromausfall bei der letzten Stelle anfangen möchte soll x gespeichert werden und ab da dann weiter.
Kann ich auch eine bestimmte Zeile und Spalte direkt zur Ausgabe ansprechen?
Danke für die Hilfe!
Zuletzt geändert von Anonymous am Freitag 27. September 2013, 20:09, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@cardeto: Die äussere Schleife ist falsch. Der Name `col` passt nicht zum Inhalt denn das ist auch eine `row` und diese Schleife wird nur *einmal* durchlaufen weil die innere Schleife, die über den selben Iterator geht, alle folgenden Zeilen aus der CSV-Datei ”aufbraucht”. Dein Programm verwendet die erste Zeile nicht. Das ist entweder ein Fehler, oder eine sehr verworrene und undurchsichtige Art eine Zeile zu ignorieren.

Statt `x` manuell zu initialisieren und in der Schleife hoch zu zählen sollte man die `enumerate()`-Funktion verwenden um Zähler und Datenzeile in der ``for``-Schleife zu iterieren.

Fallls das Python 3.x ist, dann ist `print()` eine Funktion und da setzt man üblicherweise kein Leerzeichen zwischen Funktionsname und öffnender Klammer.

Eine bestimmte Zeile kannst Du nicht direkt ansprechen ohne alle vorherigen gelesen zu haben. Die können ja underschiedlich lang sein, also kann man nicht feststellen an welchem Byte-Versatz vom Anfang der Datei eine bestimmte Zeile in der Datei beginnt.

Ich würde das ganze ja in Funktionen aufteilen. Zum Beispiel eine Generatorfunktion die Tupel mit den beiden Werten aus den Datensätzen liefert. Dann kann man sich eine schreiben die von einem Iterator eine gegebene Anzahl von Elementen einfach verwirft. `drop_n()` würde sich als Name anbieten. Auf diese Weise kann man das lesen der Daten schon mal schön von der Darstellung, ob nun per `print()` oder auf einem LCD-Display trennen.
cardeto
User
Beiträge: 11
Registriert: Freitag 27. September 2013, 18:44

Hallo BlackJack,
mit dem hier

Code: Alles auswählen

import csv
Quelle_list = []
Ziel_list = []
A = []
B = []

with open("Test.csv","r", newline="") as csvfile:
    spamreader = csv.reader(csvfile, delimiter=";", quotechar="|")
    for i, row in enumerate(spamreader):
        Quelle_list.append([i,row[0],row[4]])
        Ziel_list.append([i,row[4]])

        
        A = (Quelle_list)# nur zur Abkürzung!
        B = (Ziel_list)# nur zur Abkürzung!
#i = input ("Bitte Taste drücken: ")
#A[i]
habe ich zumindest die Datei eingelesen und kann mit A[3] auch den 3. Datensatz mit Spalte 0 und 4 anzeigen.
Warum kann ich bei A[] btw. Quelle_list[] keinen index verwenden?, siehe Input.
Danke für die Anwort.
Gruß
BlackJack

@cardeto: Schau Dir doch einfach mal die Fehlermeldung an die Du bekommst. Das müsste ``TypeError: list indices must be integers, not str`` sein. Und Datentypen und den Unterschied zwischen ganzen Zahlen und Zeichenketten müsstest Du von C++ kennen. Da kann man auch keine Zeichenkette benutzen um per Index auf ein Array-Element zuzugreifen. Das muss schon ein Wert vom Typ `int` sein. Du musst also die Zeichenkette die der Benutzer eingibt und die aus einer oder mehreren Ziffern besteht in eine ganze Zahl umwandeln.

Anmerkungen zu Quelltext: Die Namen halten sich nicht an den Style Guide for Python Code. Namen die mit Grossbuchstaben anfangen werden üblicherweise nur für Klassennamen verwendet. Ausgenommen Namen komplett in Grossbuchstaben für Konstanten.

Den konkreten Datentyp sollte man nicht in den Namen nehmen. Dann wird es schwieriger den Typ zu ändern weil man dann entweder immer überall den Namen mit ändern muss, oder man hat irreführende Namen im Quelltext. Und das man den Typ mal ändern will ist nicht ungewöhnlich. Sei es ein anderer Grunddatentyp, weil man feststellt, dass man für einen Container andere Eigenschaften braucht oder statt eines Containers auch einen Iterator verwenden kann, oder weil ein Grunddatentyp nicht mehr ausreicht und man ihn durch einen selbst geschriebenen Datentyp austauscht.

Bei Containertypen eignet sich zur Namensgebung in der Regel die Mehrzahlform des Wortes welches den Inhalt becchreibt. Also in diesem Fall zum Beispiel `quellen` und `ziele`.

Allerdings scheinen hier zwei Datenstrukturen „parallel” geführt zu werden, also zu jedem Element in `quellen` gehört das Element in `ziele` mit dem gleichen Index. Das ist kein guter Entwurf, weil es fehleranfälliger ist als zusammengehörige Daten auch tatsächlich *zusammen* zu speichern. Den Index selbst an dem Index in der Struktur zu speichern ist ausserdem redundant. Zumindest hier sehe ich keinen Grund warum man das machen sollte.

Edit: Das mit `A` und `B` zur Abkürzung verstehe ich auch nicht so richtig!?

Edit2: Ungetestet:

Code: Alles auswählen

import csv


def main():
    with open('Test.csv', 'r', newline='') as csv_file:
        reader = csv.reader(csv_file, delimiter=';', quotechar='|')
        data = [[row[0], row[4]] for row in reader]
    index = int(input('Enter index (0..{0}): '.format(len(data) - 1)))
    print(data[index])


if __name__ == '__main__':
    main()
cardeto
User
Beiträge: 11
Registriert: Freitag 27. September 2013, 18:44

Hallo BlackJack,

bezüglich TypeError: list indices must be integers, not str hatte ich gedacht das es reicht wenn ich i = int schreibe, das stand bei meinem Code jetzt nicht dabei.
Hatte aber auch nicht funktioniert.
Na die 1 Woche Grundkurs vor 7 Jahren helfen mir hier nicht wirklich weiter........

Das mit dem Index an dem Index hatte ich auch gemerkt. Gedanke war diesen Index in einer Datei zu speichern,
beim erneuten Aufruf des Programms soll ein Vergleich stattfinden und wenn Index Original Datei nicht gleich Index gespeicherte Datei ist,
dann ab Unterschied wieder Quelle, Ziel anzeigen.

Ich habe Quelle und Ziel genommen, weil ich denke das mir dann das ansprechen des LCD 1.Zeile, 2.Zeile leichter fällt.
A als Abkürzung für Quelle_list[4], A[4] lässt sich schneller tippen......lach.

Später, wenn es um die LCD Sache geht muss ich den Index der Daten rauf,
runter,auf Null setzen und halt den Vergleich(und somit Fortsetzung) mit verschiedenen Tastern realisieren.
Ich werde versuchen deine Tipps so gut wie möglich um zu setzen, nochmals ein Danke an dieser Stelle dafür.
Gruß
BlackJack

@cardeto: ``i = int`` bindet `i` an die `int()`-Funktion (beziehungseise den Datentyp `int`) Was auch immer *vorher* oder *nachher* an den Namen `i` gebunden wurde oder wird hat damit nichts zu tun.

Um auf einen bestimmten Index zuzugreifen braucht man doch nicht den Index an diesem Index als Datum speichern und vergleichen, sondern man kann *direkt* mit dem Index anfangen.

Was das die zwei Listen mit den LCD-Zeilen zu tun haben verstehe ich nicht. Im Grunde ist es komplizierter mit zwei Listen wo die zusammengehörenden Daten getrennt sind, als mit einer wo sie zusammen gespeichert sind. Auf jeden Fall ist es potentiell fehleranfälliger „parallele” Datenstrukturen zu pflegen.

Wie schnell sich ein Name tippen lässt sollte kein Kriterium sein. Bei Namen zählt wie verständlich sie sind, denn dazu sind sie da: Dem Leser zu vermitteln wofür der Wert hinter dem Namen im Kontext des Programms steht, damit mit man versteht was das Programm tut. In Zeiten in denen jeder vernünftige Editor mindestens Autovervollständigung auf Basis der offenen Dateie(n) bietet, sind auch längerer Namen kein Grund mehr mit Tipparbeit zu argumentieren.

Vielleicht solltest Du statt des konkreten Problems, oder zumindest nebenher, ein Tutorial durcharbeiten. Denn das mit dem Index und der Datei wo der zur Sicherheit wegen Stromausfällen gespeichert werden soll, klingt sehr danach als sollte man das in einem eigenen Datentyp kapseln, also eine Klasse dafür schreiben.
cardeto
User
Beiträge: 11
Registriert: Freitag 27. September 2013, 18:44

Hallo BlackJack,

natürlich gehe ich zeitgleich Tutorials durch.
Aber bei ner 50-60h Woche + Familie(3 Kinder) ist es nicht ganz so einfach.
Ich habe mal deinen Code aufgenommen und um die Eingaben erweitert,
ich hoffe ich bekomme die Ausgabe die nun am Schirm einzeilig ist, auch zweizeilig auf auf dem LCD. :roll:
Bezüglich des Stromausfalls, ich gebe ja nun den Index mit und den sollte man sich merken.

Code: Alles auswählen

import csv

def main():
    
    with open('Test.csv', 'r', newline='') as csv_file:
        reader = csv.reader(csv_file, delimiter=';', quotechar='|')
        data = [[row[0], row[4]] for row in reader]
    index = int(input('Enter Startpunkt (0..{0}): '.format(len(data) - 1)))
    while index != 53:
        print(index,data[index])
        index = index+1
        #print("Ende")if index == 53 else input("weiter")
        wahl = str (input("weiter mit(Enter),zurück(z),restart(r),Ende(e): "))
        if wahl == "z":#später Tastendruck 1
            index = index-2
            #print(index+1,data[index])
        elif wahl == "r":#später Tastendruck 2
            index = 1
        elif wahl == "e":#später Tastendruck 3
            index = 53
        elif index == 53:
            print("Ende")

if __name__ == '__main__':
    main()
Du hast in der Zeile index = int(input('Enter Startpunkt (0..{0}): '.format(len(data) - 1))) mit {0} die Zeilenanzahl (index)ausgegeben,
wie bekomme ich das hier while index !=53: hin ohne immer per Hand die max Zeilen anzugeben?
Gruß
BlackJack

@cardeto: Du gibst ja jetzt die Liste mit den zwei Elementen mit einem `print()` aus. Wenn Du das auf dem LCD ausgeben willst, dann wirst Du das halt entsprechend der API mit der Du dort Text ausgeben kannst vielleicht aufteilen, oder vielleicht auch beide Elemente durch ein Zeilenende-Zeichen getrennt zusammenfügen. Das hängt von der API ab die dafür geboten wird.

Der letzte Index der für '{0}' eingesetzt wird, kommt vom Argument der `format()`-Methode auf der Zeichenkette. So kann man den Wert natürlich auch ermitteln wenn man etwas anderes damit machen möchte.

Bei der ``while``-Schleife würde ich den Index nicht zur Bedingung machen, da würde ein einfaches `True` für eine Endlosschleife ausreichen. Das verändern des Index sollte man vielleicht auch gänzlich von der betätigten Taste abhängig machen. Dann wird das auch nicht so verwirrend dass man 2 abziehen muss um einen Eintrag zurück zu gehen wenn man nicht einfach grundsätzlich 1 drauf addiert, sondern nur wenn die entsprechende Eingabe vom Benutzer kam. Mit dem Index hat Dein Code noch ein paar andere Probleme. Der erste Index ist 0 und nicht 1. Und Du prüfst nicht ob der *Anfang* erreicht wurde wenn 'z' eingegeben wird.
cardeto
User
Beiträge: 11
Registriert: Freitag 27. September 2013, 18:44

Hallo BlackJack,

der erste Index also 0 ist bei mir die Überschrift:
DEST1"" TA1"" STOP1"" DEVICE1"" DEST2"" TA2"" STOP2"" DEVICE2"" CROSSSECTION COLOUR"" LENGTH TYPE"" WIREID CAEID""
mit index 1 wollte ich diese Anzeige übergehen.
Deine anderen Tipps gehe ich morgen an.
Gruß cardeto
BlackJack

@cardeto: Wenn die Kopfzeile der CSV-Datei nicht gebraucht wird, würde ich sie nicht in die Liste stecken. Dann muss man die erste Zeile nicht besonders behandeln.

Man könnte auch das ganze, Eingaben, Ausgaben, Verarbeitung, in verschiedene Funktionen auslagern und zum Beispiel die Eingaben von konkreten Buchstaben oder Tasten entkoppeln. Ungetestet:

Code: Alles auswählen

import csv


NEXT_KEY, PREVIOUS_KEY, FIRST_KEY, LAST_KEY = range(4)


def load_data(filename):
    with open(filename, 'r', newline='') as csv_file:
        reader = csv.reader(csv_file, delimiter=';', quotechar='|')
        next(reader)    # Skip header.
        return [[row[0], row[4]] for row in reader]


def input_int(prompt, minimum, maximum):
    prompt = prompt.format(min=minimum, max=maximum)
    while True:
        try:
            result = int(input(prompt))
        except ValueError:
            print('Eingabe muss eine Zahl sein.')
        if minimum <= result <= maximum:
            return result
        else:
            print(
                'Eingabe muss zwischen {0} und {1} liegen.'.format(
                    minimum, maximum
                )
            )


def show_values(index, values):
    value_a, value_b = values
    print(index, value_a)
    print(value_b)


def get_key():
    key_mapping = {
        '': NEXT_KEY, 'z': PREVIOUS_KEY, 'r': FIRST_KEY, 'e': LAST_KEY
    }
    while True:
        user_choice = input('weiter mit(Enter),zurück(z),restart(r),Ende(e): ')
        try:
            return key_mapping[user_choice]
        except KeyError:
            print('Unknown key: {0!r}'.format(user_choice))


def main():
    filename = 'Test.csv'
    data = load_data(filename)
    if not data:
        raise ValueError('{0!r} is empty.'.format(filename))
    last_index = len(data) - 1
    index = input_int('Startpunkt eingeben ({min}..{max}): ', 0, last_index)
    while True:
        show_values(index, data[index])
        key = get_key()
        if key == NEXT_KEY:
            if index != last_index:
                index += 1
            else:
                print('Ende')
        elif key == PREVIOUS_KEY:
            if index != 0:
                index -= 1
            else:
                print('Anfang')
        elif key == FIRST_KEY:
            index = 0
        elif key == LAST_KEY:
            index = last_index
        else:
            assert False, 'Unexpected key code'


if __name__ == '__main__':
    main()
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wenn der Spaltenname bereits in der csv-Datei steht, dann würde ich ``csv.DictReader`` verwenden. Das spart die Extrabehandlung der ersten Zeile und auf jede Spalte kann mittels Name zugeriffen werden.
Das Leben ist wie ein Tennisball.
cardeto
User
Beiträge: 11
Registriert: Freitag 27. September 2013, 18:44

Hallo BlackJack
ich probiere seit 4h eine Schleife zur Ausgabe mit dem Code zu machen:

Code: Alles auswählen

#!/usr/bin/python
#
# HD44780 LCD Test Script for
# Raspberry Pi
#
# Author : Matt Hawkins
# Site   : http://www.raspberrypi-spy.co.uk
# 
# Date   : 26/07/2012
#

# The wiring for the LCD is as follows:
# 1 : GND
# 2 : 5V
# 3 : Contrast (0-5V)*
# 4 : RS (Register Select)
# 5 : R/W (Read Write)       - GROUND THIS PIN
# 6 : Enable or Strobe
# 7 : Data Bit 0             - NOT USED
# 8 : Data Bit 1             - NOT USED
# 9 : Data Bit 2             - NOT USED
# 10: Data Bit 3             - NOT USED
# 11: Data Bit 4
# 12: Data Bit 5
# 13: Data Bit 6
# 14: Data Bit 7
# 15: LCD Backlight +5V**
# 16: LCD Backlight GND

#import
import RPi.GPIO as GPIO
import time

# Define GPIO to LCD mapping
LCD_RS = 7
LCD_E  = 8
LCD_D4 = 25 
LCD_D5 = 24
LCD_D6 = 23
LCD_D7 = 18

# Define some device constants
LCD_WIDTH = 16    # Maximum characters per line
LCD_CHR = True
LCD_CMD = False

LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line 

# Timing constants
E_PULSE = 0.00005
E_DELAY = 0.00005

def main():
  # Main program block

  GPIO.setmode(GPIO.BCM)       # Use BCM GPIO numbers
  GPIO.setup(LCD_E, GPIO.OUT)  # E
  GPIO.setup(LCD_RS, GPIO.OUT) # RS
  GPIO.setup(LCD_D4, GPIO.OUT) # DB4
  GPIO.setup(LCD_D5, GPIO.OUT) # DB5
  GPIO.setup(LCD_D6, GPIO.OUT) # DB6
  GPIO.setup(LCD_D7, GPIO.OUT) # DB7

  # Initialise display
  lcd_init()

  # Send some test
  lcd_byte(LCD_LINE_1, LCD_CMD)
  lcd_string("Rasbperry Pi")
  lcd_byte(LCD_LINE_2, LCD_CMD)
  lcd_string("Model B")

  time.sleep(3) # 3 second delay

  # Send some text
  lcd_byte(LCD_LINE_1, LCD_CMD)
  lcd_string("Raspberrypi-spy")
  lcd_byte(LCD_LINE_2, LCD_CMD)
  lcd_string(".co.uk")

  time.sleep(20)

def lcd_init():
  # Initialise display
  lcd_byte(0x33,LCD_CMD)
  lcd_byte(0x32,LCD_CMD)
  lcd_byte(0x28,LCD_CMD)
  lcd_byte(0x0C,LCD_CMD)  
  lcd_byte(0x06,LCD_CMD)
  lcd_byte(0x01,LCD_CMD)  

def lcd_string(message):
  # Send string to display

  message = message.ljust(LCD_WIDTH," ")  

  for i in range(LCD_WIDTH):
    lcd_byte(ord(message[i]),LCD_CHR)

def lcd_byte(bits, mode):
  # Send byte to data pins
  # bits = data
  # mode = True  for character
  #        False for command

  GPIO.output(LCD_RS, mode) # RS

  # High bits
  GPIO.output(LCD_D4, False)
  GPIO.output(LCD_D5, False)
  GPIO.output(LCD_D6, False)
  GPIO.output(LCD_D7, False)
  if bits&0x10==0x10:
    GPIO.output(LCD_D4, True)
  if bits&0x20==0x20:
    GPIO.output(LCD_D5, True)
  if bits&0x40==0x40:
    GPIO.output(LCD_D6, True)
  if bits&0x80==0x80:
    GPIO.output(LCD_D7, True)

  # Toggle 'Enable' pin
  time.sleep(E_DELAY)    
  GPIO.output(LCD_E, True)  
  time.sleep(E_PULSE)
  GPIO.output(LCD_E, False)  
  time.sleep(E_DELAY)      

  # Low bits
  GPIO.output(LCD_D4, False)
  GPIO.output(LCD_D5, False)
  GPIO.output(LCD_D6, False)
  GPIO.output(LCD_D7, False)
  if bits&0x01==0x01:
    GPIO.output(LCD_D4, True)
  if bits&0x02==0x02:
    GPIO.output(LCD_D5, True)
  if bits&0x04==0x04:
    GPIO.output(LCD_D6, True)
  if bits&0x08==0x08:
    GPIO.output(LCD_D7, True)

  # Toggle 'Enable' pin
  time.sleep(E_DELAY)    
  GPIO.output(LCD_E, True)  
  time.sleep(E_PULSE)
  GPIO.output(LCD_E, False)  
  time.sleep(E_DELAY)   

if __name__ == '__main__':
  main()
leider schaffe ich es nicht in Send some Text es so zu machen,
das meine Ausgabe aus der csv angezeigt wird.
Ich habe es mit deinem Code:

Code: Alles auswählen

import csv


NEXT_KEY, PREVIOUS_KEY, FIRST_KEY, LAST_KEY = range(4)


def load_data(filename):
    with open(filename, 'r', newline='') as csv_file:
        reader = csv.reader(csv_file, delimiter=';', quotechar='|')
        next(reader)    # Skip header.
        return [[row[0], row[4]] for row in reader]


def input_int(prompt, minimum, maximum):
    prompt = prompt.format(min=minimum, max=maximum)
    while True:
        try:
            result = int(input(prompt))
        except ValueError:
            print('Eingabe muss eine Zahl sein.')
        if minimum <= result <= maximum:
            return result
        else:
            print(
                'Eingabe muss zwischen {0} und {1} liegen.'.format(
                    minimum, maximum
                )
            )


def show_values(index, values):
    value_a, value_b = values
    print(index, value_a)
    print(value_b)


def get_key():
    key_mapping = {
        '': NEXT_KEY, 'z': PREVIOUS_KEY, 'r': FIRST_KEY, 'e': LAST_KEY
    }
    while True:
        user_choice = input('weiter mit(Enter),zurück(z),restart(r),Ende(e): ')
        try:
            return key_mapping[user_choice]
        except KeyError:
            print('Unknown key: {0!r}'.format(user_choice))


def main():
    filename = 'Test.csv'
    data = load_data(filename)
    if not data:
        raise ValueError('{0!r} is empty.'.format(filename))
    last_index = len(data) - 1
    index = input_int('Startpunkt eingeben ({min}..{max}): ', 0, last_index)
    while True:
        show_values(index, data[index])
        key = get_key()
        if key == NEXT_KEY:
            if index != last_index:
                index += 1
            else:
                print('Ende')
        elif key == PREVIOUS_KEY:
            if index != 0:
                index -= 1
            else:
                print('Anfang')
        elif key == FIRST_KEY:
            index = 0
        elif key == LAST_KEY:
            index = last_index
        else:
            assert False, 'Unexpected key code'


if __name__ == '__main__':
    main()
probiert, ich weis aber nicht an welcher Stelle ich den einfügen muß.
Kannst du mir nen Tipp geben?
Danke
Gruß
Cardeto
Sirius3
User
Beiträge: 17753
Registriert: Sonntag 21. Oktober 2012, 17:20

@cardeto: das ist ja furchtbarer Code zum Ansteuern Deines LCD-Tickers. Einrücktiefe von Python ist immer 4 Leerzeichen und nicht 2; es wimmelt nur so von Wiederholungen und es gibt keine Trennung zwischen Low- und Highlevel.

Code: Alles auswählen

import RPi.GPIO as GPIO
import time

class LCDisplay:
    # The wiring for the LCD is as follows:
    # 1 : GND
    # 2 : 5V
    # 3 : Contrast (0-5V)*
    # 4 : RS (Register Select)
    # 5 : R/W (Read Write)       - GROUND THIS PIN
    # 6 : Enable or Strobe
    # 7 : Data Bit 0             - NOT USED
    # 8 : Data Bit 1             - NOT USED
    # 9 : Data Bit 2             - NOT USED
    # 10: Data Bit 3             - NOT USED
    # 11: Data Bit 4
    # 12: Data Bit 5
    # 13: Data Bit 6
    # 14: Data Bit 7
    # 15: LCD Backlight +5V**
    # 16: LCD Backlight GND
    
    # Define GPIO to LCD mapping
    LCD_RS = 7
    LCD_E  = 8
    LCD_D4 = 25 
    LCD_D5 = 24
    LCD_D6 = 23
    LCD_D7 = 18
    
    # Define some device constants
    LCD_WIDTH = 16    # Maximum characters per line
    LCD_CHR = True
    LCD_CMD = False
    
    LCD_LINES = [0x80, 0xC0] # LCD RAM address for the 1st/2nd line
    
    # Timing constants
    E_PULSE = 0.00005
    E_DELAY = 0.00005
    
    INIT_SEQ = (0x33, 0x32, 0x28, 0x0C, 0x06, 0x01)
    BIT_CMDS = ((1, LCD_D4), (2, LCD_D5), (4, LCD_D6), (8, LCD_D7))
    ALL_GPIO = (LCD_E, LCD_RS, LCD_D4, LCD_D5, LCD_D6, LCD_D7)

    def __init__(self):
        GPIO.setmode(GPIO.BCM)       # Use BCM GPIO numbers
        for gpio in self.ALL_GPIO:
            GPIO.setup(gpio, GPIO.OUT)
        # Initialise display
        for cmd in self.INIT_SEQ:
            self._lcd_byte(cmd, self.LCD_CMD)

    def _lcd_nibble(self, bits):
        for mask, cmd in self.BIT_CMDS:
            GPIO.output(cmd, bool(bits&mask))
        # Toggle 'Enable' pin
        time.sleep(self.E_DELAY)    
        GPIO.output(self.LCD_E, True)  
        time.sleep(self.E_PULSE)
        GPIO.output(self.LCD_E, False)  
        time.sleep(self.E_DELAY)      

    def _lcd_byte(self, bits, mode):
        # Send byte to data pins
        # bits = data
        # mode = True  for character
        #        False for command
        GPIO.output(self.LCD_RS, mode)
        self._lcd_nibble(bits>>4)
        self._lcd_nibble(bits)

    def __setitem__(self, line, message):
        # Send string to display
        self._lcd_byte(self.LCD_LINES[line], self.LCD_CMD)
        for char in message.ljust(self.LCD_WIDTH):
            self._lcd_byte(ord(char), self.LCD_CHR)

def main():
    lcd = LCDisplay()
    # Send some test
    lcd[0]="Rasbperry Pi"
    lcd[1]="Model B"
    time.sleep(3) # 3 second delay

    # Send some text
    lcd[0]="Raspberrypi-spy"
    lcd[1]=".co.uk"
    time.sleep(20)


if __name__ == '__main__':
    main()
Achso, in »show_values« sollen doch die Daten aus der csv-Datei angezeigt werden, da wäre wohl der richtige Ort zum Ansprechen des Displays.
cardeto
User
Beiträge: 11
Registriert: Freitag 27. September 2013, 18:44

Hallo Sirius3,

danke für diese optimierte Version, aber bei deinem Code bekomme ich folgende Fehlermeldung

Code: Alles auswählen

Warning (from warnings module):
  File "/home/pi/testlcd.py", line 49
    GPIO.setup(gpio, GPIO.OUT)
RuntimeWarning: This channel is already in use, continuing anyway.  Use GPIO.setwarnings(False) to disable warnings.
Traceback (most recent call last):                             das ist ok
  File "/home/pi/testlcd.py", line 93, in <module>
    main()
  File "/home/pi/testlcd.py", line 80, in main
    lcd = LCDisplay()
  File "/home/pi/testlcd.py", line 52, in __init__
    self._lcd_byte(cmd, self.LCD_CMD)
  File "/home/pi/testlcd.py", line 70, in _lcd_byte
    self._lcd_nibble(bits>>4)                                       ist hier ein > zuviel?
  File "/home/pi/testlcd.py", line 56, in _lcd_nibble
    GPIO.output(cmd, bool(bits&mask))              Semikolon ist wohl falsch, bool erwartet nur 1 Argument
NameError: global name 'amp' is not defined
Kannst Du mal schauen was da nicht richtig läuft?
Gruß
Cardeto
Sirius3
User
Beiträge: 17753
Registriert: Sonntag 21. Oktober 2012, 17:20

@cardeto: das ist der wohlbekannte Forumsfehler, dass & immer als & dargestellt wird.
BlackJack

@cardeto: Da ist kein ``>`` zu viel. Das ist kein Vergleich sondern der ``>>``-Operator.
cardeto
User
Beiträge: 11
Registriert: Freitag 27. September 2013, 18:44

@sirius3

na super, so ein kleiner Fehler und ich steh da.
Jetzt geht die Ansteuerung, nur beim 2. starten gibt das Display nur hmm....Sonderzeichen/Müll aus.
Ich denke das sich hier die Bits addieren und ich vorher zurück setzen muss.
Ich schau mal ob ich das hin bekomme.
Gruß
Cardeto
cardeto
User
Beiträge: 11
Registriert: Freitag 27. September 2013, 18:44

@BlackJack
ok, dann wird aus 1111 0000
0000 1111 4 bits nach rechts...oder?
BlackJack

@cardeto: Mal schauen:

Code: Alles auswählen

In [36]: int('11110000', 2)
Out[36]: 240

In [37]: int('11110000', 2) >> 4
Out[37]: 15

In [38]: '{0:08b}'.format(int('11110000', 2) >> 4)
Out[38]: '00001111'
Sieht so aus. :-)
Benutzeravatar
snafu
User
Beiträge: 6740
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

@cardeto: Wenn du dich mit irgendwelchen seriellen Schnittstellen "unterhälst", dann solltest du dich IMHO mindestens mit den Grundlagen zu Bitoperationen beschäftigen. Das mag zwar ziemlich anspruchsvoll und aufwändig sein, wenn man bisher nichts damit zu tun hatte, aber nur so verstehst du, was wirklich vor sich geht und erlangst die Fähigkeit, eigene Lösungen zu entwickeln. Ich glaube ehrlich gesagt momentan nicht, dass du die Lösung von Sirius3 wirklich verstanden hast - nichts für ungut...

EDIT: Meine Aussage ist natürlich auch auf den Rasperry Pi anwendbar.
Antworten