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

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: 14494
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: 14494
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: 14494
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: 14494
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: 14494
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: 14494
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: 14494
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.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Landixus: da gibt es einen Trick: man schreibt seine Programme so, dass man sie noch versteht. Z.B. schreibt man eine rpm2power-Funktion und ruft die mit verschiedenen Parametern auf und schaut, was rauskommt, dann schreibt man Schleifen und schaut, wie sich bei verändernden Parametern wie Werte ändern.

Oder man schreibt ein Programm, das auf Knopfdrücken reagiert, erstmal nur „an“ /„aus“, dann vielleicht eine Variable, die hoch oder runterzählt.

Wenn man beides kann, kann man die beiden Teile kombinieren.
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Also ich habs jetzt am laufen mit dem alten Code und das klappt super, die Ausgabe/Übergabe an JS habe ich auch hin bekommen.

Das interpolieren baut mir jetzt ein Kollege ein, ich poste das Ergebnis natürlich hier, evtl. hilft es noch anderen.

Was ich aber wirklich sagen muss, das hier sehr nette Leute unterwegs sind und sehr hilfsbereit. (Das ist nicht überall so).

Was so Logik und Rechnen/Programmieren angeht hab ich Irgendwie gefehlt in der Schule, oder ich erinnere mich nicht mehr weil ich zu alt bin. :)

Deswegen arbeite ich wohl im Einkauf, da sind die Programme schon da.
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Falls doch noch Jemand Interesse hat, kann hier kurz einsteigen:

http://www.forum-raspberrypi.de/Thread- ... #pid281615

Ich hoffe hat keiner was gegen das verlinken.
Biete da auch noch mal 150.

ansonsten stampf ich das Projekt ein.
Benutzeravatar
Landixus
User
Beiträge: 49
Registriert: Mittwoch 26. April 2017, 09:38

Erledigt in JS

https://www.instructables.com/id/Using- ... ss-Device/

Auch wenn es hier nicht mit Python zum Erfolg geführt hat, danke ich trotzdem für eure Geduld. :P
Antworten