Werte aus Tabelle / Matrix / Array, oder Liste?

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

ich rede so gerne mit mir selber :)


Code: Alles auswählen

...
    LEVEL = count
    RPM = p.RPM()
    RPM = (int(RPM+1))
    time.sleep(SAMPLE_TIME)
    print('Power',calculate_power(LEVEL, RPM),'Level', count, "RPM={}".format(int(RPM+1)))  
    with open ('power') as output:
        output.write (calculate_power(LEVEL, RPM)
        output.close()
    time.sleep(1)
....
Korrekt? :D
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Landixus hat geschrieben:Korrekt?
Leider nein. Du öffnest die Datei zum Lesen, versuchst hinein zu schreiben und im with-Kontext brauchst Du sie auch nicht zu schließen.

@Liffi: JSON ist kein JavaScript. Da steckt zwar JavaScript im Namen, aber der Eindruck täuscht. Es ist ein Datenformat.
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Ich hab jetzt ein Programm gefunden was die Shell-Ausgabe lesen kann.
I wesentlichen geht es mir ja um den Power Wert.

https://github.com/extrabacon/python-sh ... and-python

damit sollte ich klar kommen.

Ist zwar eine Bastellösung, aber eine die vielleicht funktioniert.
Ich probiere das nachher mal aus :)
Liffi
User
Beiträge: 153
Registriert: Montag 1. Januar 2007, 17:23

kbr hat geschrieben: @Liffi: JSON ist kein JavaScript. Da steckt zwar JavaScript im Namen, aber der Eindruck täuscht. Es ist ein Datenformat.
Ich hatte in Erinnerung, dass es valides JavaScript ist. Mein Browser enttäuscht mich da aber ein bisschen.

Code: Alles auswählen

{"JSON":"ro
cks!"}
Da stolpert mein Firefox drüber, über folgendes aber nicht:

Code: Alles auswählen

{JSON:"ro
cks!"}
Hätte eigentlich erwartet, dass das erste super gehen müsste.
BlackJack

@Liffi: Das erste geht auch wenn da nicht irgendwas komisches in der zweiten Zeichenkette wäre. Wenn ich das markiere und in meine Shell mit IPython kopiere passieren komische Dinge. Da sind irgendwelche unsichtbare Steuerzeichen nach dem o von rocks.

Es ging glaube ich auch mehr darum dem OP zu vermitteln das JSON kein JavaScript ist, weil der mehrfach von JSON-Programmen gesprochen hat und *dann* die Frage aufkam ob JSON einfach JavaScript ist. JSON ist halt keine Programmiersprache und auch unabhängig von einer Programmiersprache verwendbar, beziehungsweise mit allen möglichen Programmiersprachen verwendbar.

Edit: Zwischen o und c von rocks ist ein U+2028 LINE SEPARATOR Zeichen was von JavaScript (und auch Python) als Zeilenende interpretiert wird und damit hat man mit der zweiten Zeichenkette eine die nicht syntaxkonform beendet wird, weil das Ende erst in der nächsten Zeile steht.
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Hab ich verstanden mit JSON und Javascript.

Was ich aber schade finden würde wenn das Stücken Code von @__deets__ nicht bei mir verarbeitet wird:

Code: Alles auswählen

from __future__ import print_function
 
import math
 
LEVEL_TO_POWER = {
    1: [6,12,20,29,40,53,69,79,92,106,121],
    2: [8,16,26,38,53,68,88,103,120,138,152],
    3: [9,20,32,47,66,84,107,125,148,172,186],
    4: [11,23,39,56,79,101,126,150,173,206,219],
    5: [13,27,45,65,92,117,145,175,202,238,254],
    6: [15,31,52,75,105,135,166,202,231,275,289],
    7: [16,35,58,85,118,152,185,226,260,305,332],
    8: [18,39,65,96,131,169,208,249,289,333,375],
    9: [19,42,71,104,144,184,227,272,318,361,408],
    10:[21,46,77,113,157,199,245,295,345,386,442],
    11:[23,50,84,123,170,216,262,318,372,413,480],
    12:[24,53,89,131,183,230,279,342,398,441,512],
    13:[26,56,94,139,196,245,296,365,424,468,548],
    14:[28,60,101,148,209,261,318,389,449,494,585],
    15:[30,64,108,158,222,277,337,415,476,518,620],
    16:[32,68,115,168,235,296,355,439,503,548,658],
    17:[33,72,122,177,248,312,373,463,530,576,694],
    18:[35,76,129,187,261,328,390,484,556,606,727],
    19:[37,79,134,195,274,342,407,507,572,632,763],
    20:[39,83,140,204,287,354,424,528,598,659,790],
    21:[40,87,146,213,300,368,442,551,616,689,812],
    22:[42,91,153,223,313,385,461,574,645,720,840],
    23:[44,95,160,234,326,401,479,598,673,752,872],
    24:[47,101,171,246,340,418,501,625,706,788,908],
    }
 
UPPER_LIMIT = len(LEVEL_TO_POWER.values()[0]) - 2
 
def clamp(v, lower, upper):
    return max(min(v, upper), lower)
 
 
def rpm2index(rpm):
    # clamping downto a range that never exceeds
    # the power level size - 2 so we can interpolate
    i = clamp((rpm - 20) // 10, 0, UPPER_LIMIT)
    f = (rpm - (i * 10 + 20)) / 10.0
    return i, f
 
 
def rpm2power(rpm):
    i, f = rpm2index(rpm)
    a = LEVEL_TO_POWER[1][i]
    b = LEVEL_TO_POWER[1][i + 1]
    return a + (b - a) * f
 
 
def main():
    for rpm in xrange(20, 131):
        print("RPM:", rpm, "POWER:", rpm2power(rpm))
 
 
if __name__ == '__main__':
    main()
Das muss ich noch irgendwie mit meinem verbaut bekommen. *verdammt :)
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Ich hab noch einmal alles gegeben :)

Kann das jetzt mit @__deets__ seinem code so richtig sein wie ich das eingebaut habe?
Ich habe alle Zeilenfehler entfernt und meinen code von der Syntax auch geprüft.
Ab Zeile 115 gehts los *schwitz

Code: Alles auswählen

#!/usr/bin/env python
import time
import pigpio


class reader:

    def __init__(self, pi, gpio, pulses_per_rev=1.0, weighting=0, min_RPM=5):

        self.pi = pi
        self.gpio = gpio
        self.pulses_per_rev = pulses_per_rev

        if min_RPM > 1000:
            min_RPM = 1000
            elif min_RPM < 1:
                min_RPM = 1

        self.min_RPM = min_RPM

        self._watchdog = 200  # Milliseconds.

        if weighting < 0:
            weighting = 0
        elif weighting > 0:
            weighting = 0

        self._new = 1 - weighting   # Weighting for new reading.
        self._old = weighting       # Weighting for old reading.

        self._high_tick = None
        self._period = None

        pi.set_mode(gpio, pigpio.INPUT)

        self._cb = pi.callback(gpio, pigpio.RISING_EDGE, self._cbf)
        pi.set_watchdog(gpio, self._watchdog)

    def _cbf(self, gpio, level, tick):

        if level == 1:  # Rising edge.

            if self._high_tick is not None:
                t = pigpio.tickDiff(self._high_tick, tick)

            if self._period is not None:
                self._period = (self._old * self._period) + (self._new * t)
            else:
                self._period = t

            self._high_tick = tick

            elif level == 2:  # Watchdog timeout.

                if self._period is not None:
                    if self._period < 2000000000:
                        self._period += (self._watchdog * 1000)

    def RPM(self):

        RPM = 0
        if self._period is not None:
            RPM = 60000000 / (self._period * self.pulses_per_rev)
            if RPM < self.min_RPM:
                RPM = 0

        return RPM

    def cancel(self):

        self.pi.set_watchdog(self.gpio, 0)  # cancel watchdog
        self._cb.cancel()
if __name__ == "__main__":
    from __future__ import print_function
    import math
    import time
    import pigpio
    import readRPM
    import RPi.GPIO as GPIO
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(20, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    count = 5
    RPM_GPIO = 4
    RUN_TIME = 9600.0
    SAMPLE_TIME = 1.0


LEVEL_TO_POWER = {
    1: [6, 12, 20, 29, 40, 53, 69, 79, 92, 106, 121],
    2: [8, 16, 26, 38, 53, 68, 88, 103, 120, 138, 152],
    3: [9, 20, 32, 47, 66, 84, 107, 125, 148, 172, 186],
    4: [11, 23, 39, 56, 79, 101, 126, 150, 173, 206, 219],
    5: [13, 27, 45, 65, 92, 117, 145, 175, 202, 238, 254],
    6: [15, 31, 52, 75, 105, 135, 166, 202, 231, 275, 289],
    7: [16, 35, 58, 85, 118, 152, 185, 226, 260, 305, 332],
    8: [18, 39, 65, 96, 131, 169, 208, 249, 289, 333, 375],
    9: [19, 42, 71, 104, 144, 184, 227, 272, 318, 361, 408],
    10: [21, 46, 77, 113, 157, 199, 245, 295, 345, 386, 442],
    11: [23, 50, 84, 123, 170, 216, 262, 318, 372, 413, 480],
    12: [24, 53, 89, 131, 183, 230, 279, 342, 398, 441, 512],
    13: [26, 56, 94, 139, 196, 245, 296, 365, 424, 468, 548],
    14: [28, 60, 101, 148, 209, 261, 318, 389, 449, 494, 585],
    15: [30, 64, 108, 158, 222, 277, 337, 415, 476, 518, 620],
    16: [32, 68, 115, 168, 235, 296, 355, 439, 503, 548, 658],
    17: [33, 72, 122, 177, 248, 312, 373, 463, 530, 576, 694],
    18: [35, 76, 129, 187, 261, 328, 390, 484, 556, 606, 727],
    19: [37, 79, 134, 195, 274, 342, 407, 507, 572, 632, 763],
    20: [39, 83, 140, 204, 287, 354, 424, 528, 598, 659, 790],
    21: [40, 87, 146, 213, 300, 368, 442, 551, 616, 689, 812],
    22: [42, 91, 153, 223, 313, 385, 461, 574, 645, 720, 840],
    23: [44, 95, 160, 234, 326, 401, 479, 598, 673, 752, 872],
    24: [47, 101, 171, 246, 340, 418, 501, 625, 706, 788, 908],
    }
pi = pigpio.pi()
p = readRPM.reader(pi, RPM_GPIO)
input_state = false

UPPER_LIMIT = len(LEVEL_TO_POWER.values()[0]) - 2


def clamp(v, lower, upper):
    return max(min(v, upper), lower)


def rpm2index(rpm):
    # clamping downto a range that never exceeds
    # the power level size - 2 so we can interpolate
    i = clamp((rpm - 20) // 10, 0, UPPER_LIMIT)
    f = (rpm - (i * 10 + 20)) / 10.0
    return i, f


def rpm2power(rpm):
    i, f = rpm2index(rpm)
    a = LEVEL_TO_POWER[1][i]
    b = LEVEL_TO_POWER[1][i + 1]
    return a + (b - a) * f


def main():
    for rpm in xrange(20, 131):
        start = time.time()
        while (time.time() - start) < RUN_TIME:
            input_state = GPIO.input(20)
            if input_state:
                if count < 24:
                    count = count + 1
                    LEVEL = count
                    print("LEVEL", count"RPM:", rpm, "POWER:", rpm2power(rpm))
                    time.sleep(SAMPLE_TIME)
            input_state = GPIO.input(20)
            if input_state:
                if count > 1:
                    count = count - 1
                    LEVEL = count
                    print("LEVEL", count"RPM:", rpm, "POWER:", rpm2power(rpm))
                    time.sleep(SAMPLE_TIME)
p.cancel()
pi.stop()
if __name__ == '__main__':
    main()
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du hast immer noch die hart-kodierte Stufe eins in rpm2power.

Das muss einen weiteren Parameter bekommen, level, und der muss statt der 1 benutzt werden.
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

__deets__ hat geschrieben:Du hast immer noch die hart-kodierte Stufe eins in rpm2power.

Das muss einen weiteren Parameter bekommen, level, und der muss statt der 1 benutzt werden.
Also:

Code: Alles auswählen

LEVEL = 5  # We start at LEVEL 5


def rpm2power(rpm):

    i, f = rpm2index(rpm)
    a = LEVEL_TO_POWER[LEVEL][i]
    b = LEVEL_TO_POWER[LEVEL][i + LEVEL]
    return a + (b - a) * f


def main():
    for rpm in xrange(20, 131):
        start = time.time()
        while (time.time() - start) < RUN_TIME:
            input_state = GPIO.input(20)
            if input_state:
                if LEVEL < 24:
                    LEVEL = count + 1
                    print("LEVEL", LEVEL"RPM:", rpm, "POWER:", rpm2power(rpm))
                    time.sleep(SAMPLE_TIME)
das

Code: Alles auswählen

 LEVEL = count
brauch ich dann ja nicht mehr? Ich glaub so ganz langsam komme ich dahinter.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nein. Du sollst es als PARAMETER uebergeben. Das arbeiten mit globalem Zustand ist ueblicherweise ungesund und Ursache fuer schwer zu ermittelnde Fehler.

Code: Alles auswählen

def rpm2power(rpm, level):
      ...
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

__deets__ hat geschrieben:Nein. Du sollst es als PARAMETER uebergeben. Das arbeiten mit globalem Zustand ist ueblicherweise ungesund und Ursache fuer schwer zu ermittelnde Fehler.

Code: Alles auswählen

def rpm2power(rpm, level):
      ...
Boah, so langsam macht mich das fertig. Ich denke immer AH! und dann wieder doch nicht :(

also...:

Code: Alles auswählen


#  LEVEL = 5  # We start at LEVEL 5  fliegt wieder raus, bloss wie sag ich ihm das wir mit 5 Starten?
 
 
def rpm2power(rpm, LEVEL=5):  # geht das so?
 
    i, f = rpm2index(rpm)
    a = LEVEL_TO_POWER[LEVEL][i]
    b = LEVEL_TO_POWER[LEVEL][i + LEVEL]
    return a + (b - a) * f
 
 
def main():
    for rpm in xrange(20, 131):
        start = time.time()
        while (time.time() - start) < RUN_TIME:
            input_state = GPIO.input(20)
            if input_state:
                if LEVEL < 24:
                    LEVEL = count + 1
                    print("LEVEL", LEVEL"RPM:", rpm, "POWER:", rpm2power(rpm))
                    time.sleep(SAMPLE_TIME)
:D Oder?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ob das geht kannst du ja ausprobieren. Nimm dir einfach *MEIN* komplettes Beispiel, fuer es aus. Dann bau das Level ein, zB noch mal als for-schleife drumrum um die innere Schleife, und guck, was passiert. Proggrammieren und probieren teilen sich nicht von ungefaehr das "Pro" - und noch ein bisschen mehr ;)

Und LEVEL sollte *NICHT* gross geschrieben werden, weil das eine Konstante impliziert. Aber grundsaetzlich sollte es gehen. Nur wuerde ich keinen Default-Wert 5 angeben, der ist sinnlos. Genausowenig wie es eine standardmaessige RPM gibt. Da sollte schon beides ein Pflichtparameter sein.
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

__deets__ hat geschrieben:Ob das geht kannst du ja ausprobieren. Nimm dir einfach *MEIN* komplettes Beispiel, fuer es aus. Dann bau das Level ein, zB noch mal als for-schleife drumrum um die innere Schleife, und guck, was passiert. Proggrammieren und probieren teilen sich nicht von ungefaehr das "Pro" - und noch ein bisschen mehr ;)

Und LEVEL sollte *NICHT* gross geschrieben werden, weil das eine Konstante impliziert. Aber grundsaetzlich sollte es gehen. Nur wuerde ich keinen Default-Wert 5 angeben, der ist sinnlos. Genausowenig wie es eine standardmaessige RPM gibt. Da sollte schon beides ein Pflichtparameter sein.
Ich kann das immer erst zu Hause ausprobieren, bin ja auf der Arbeit :oops:

der Default Wert is da, weil ich am Crosstrainer ja mit Level 5 starte. Wenn ich dann die Taster + oder - drücke wechsel ich ja die LEVEL entsprechend.

Ich probier das heute Abend gleich aus! :D
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du kannst einen Defaultwert woanders haben, aber in dieser Hilfsfuntion sollte er nicht sein. Die wirst du *IMMER* mit etwas konkretem aufrufen, wenn du das nicht machst ist das ein Fehler.
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Code: Alles auswählen

def rpm2power(rpm, level):
    i, f = rpm2index(rpm)
    a = LEVEL_TO_POWER[level][i]
    b = LEVEL_TO_POWER[level][i + level]
    return a + (b - a) * f


def main():
    for rpm in xrange(20, 131):
        start = time.time()
        while (time.time() - start) < RUN_TIME:
            input_state = GPIO.input(20)
            if input_state == False:
                if level < 24:
                    level = count + 1
                    #  level = count
                    print("LEVEL", level, "RPM:", rpm, "POWER:", rpm2power(rpm))
                    time.sleep(SAMPLE_TIME)
            input_state = GPIO.input(21)
            if input_state == False:
                if level > 1:
                    level = count - 1
                    #  level = count
                    print("LEVEL", level, "RPM:", rpm, "POWER:", rpm2power(rpm))
                    time.sleep(SAMPLE_TIME)
    print("LEVEL", level, "RPM:", rpm, "POWER:", rpm2power(rpm))

p.cancel()
pi.stop()
if __name__ == '__main__':
    main()
das gibt mir jetzt ein:

Code: Alles auswählen

Traceback (most recent call last):
  File "./9powerx.py", line 165, in <module>
    main()
  File "./9powerx.py", line 148, in main
    if level < 24:
UnboundLocalError: local variable 'level' referenced before assignment
pi@carcam:~/ant-cycling-power $
wenn ich GPIO 21 oder 20 High setzte, also den Taster drücke.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich habe nicht gesagt du sollst das überall ändern. Sondern nur in meiner Funktion.
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Ich hab bei festhalten von der LevelTaste schon mal eine Ausgabe :)

Code: Alles auswählen

pi@carcam:~/ant-cycling-power $ ./9powerx.py
LEVEL 6 RPM: 20 POWER: 15.0
LEVEL 6 RPM: 20 POWER: 15.0
LEVEL 6 RPM: 20 POWER: 15.0
LEVEL 4 RPM: 20 POWER: 11.0
LEVEL 4 RPM: 20 POWER: 11.0
LEVEL 4 RPM: 20 POWER: 11.0
Allerdings zählt es 2 level runter, oder 2 level hoch, die rpm verändern sich leider gar nicht wenn ich die mit dem taster simulieren :(

Code: Alles auswählen

pi = pigpio.pi()
p = readRPM.reader(pi, RPM_GPIO)

UPPER_LIMIT = len(LEVEL_TO_POWER.values()[0]) - 2


def clamp(v, lower, upper):
    return max(min(v, upper), lower)


def rpm2index(rpm):
    # clamping downto a range that never exceeds
    # the power level size - 2 so we can interpolate
    i = clamp((rpm - 20) // 10, 0, UPPER_LIMIT)
    f = (rpm - (i * 10 + 20)) / 10.0
    return i, f


def rpm2power(rpm, level):
    i, f = rpm2index(rpm)
    a = LEVEL_TO_POWER[level][i]
    b = LEVEL_TO_POWER[level][i + level]
    return a + (b - a) * f


def main():
    for rpm in xrange(20, 131):
        start = time.time()
        while (time.time() - start) < RUN_TIME:
            input_state = GPIO.input(20)
            if input_state == False:
                if count < 24:
                    level = count + 1
                    # level = count
                    print("LEVEL", level, "RPM:", rpm, "POWER:", rpm2power(rpm, level))
                    time.sleep(SAMPLE_TIME)
            input_state = GPIO.input(21)
            if input_state == False:
                if count > 1:
                    level = count - 1
                   # level = count
                    print("LEVEL", level, "RPM:", rpm, "POWER:", rpm2power(rpm, level))
                    time.sleep(SAMPLE_TIME)
        print("LEVEL", level, "RPM:", rpm, "POWER:", rpm2power(rpm, level))

p.cancel()
pi.stop()
if __name__ == '__main__':
    main()
was ist denn jetzt schon wieder falsch?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Meine Güte. Du versuchst echt gar nicht zu verstehen, was da passiert, oder? Die rpm2power Funktion hat dreimal eine 1 enthalten. Davon waren nur die in den Klammern das hart kodierte Level. Wie man sich auch leicht denkt, weil das Dictionary so aufgebaut ist.

Und dann wird zwischen zwei werten interpoliert. A und b. Und b ist natürlich der Wert nach a in der Liste. Also stand da "+1". Da das Level zu addieren ist unsinn.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und das deine Rpms konstant bleiben ist auch klar: du baust eine for-schleife um eine while Schleife, und die letztere verlässt du nie. Rpm Steigt also nicht an.
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Doch schon, aber dafür langt mein Horizont halt nicht aus und ich weiß wo meine Grenzen sind.

Trotzdem danke für den Versuch mir zu helfen.
Antworten