Hallo,
du kannst mit der Programmiersprache Python ein Skript erstellen, dass die Excel-Datei ausliest.
Grüße
Dennis
Hallo,
du kannst mit der Programmiersprache Python ein Skript erstellen, dass die Excel-Datei ausliest.
Grüße
Dennis
Hallo,
Aber das kann ich eigentlich auch alles mit while lösen (glaube ich jedenfalls)
und mit 'if'. Das Konzept könnte so aussehen: In einer Dauerschleife wird die aktuelle Position abgefragt, dann wird mit 'if'-Abfragen den Unterschied zwischen Ist und Soll ermittelt und entsprechend reagiert, sprich dem betreffenden Motor einen Impuls senden .
Zu deinem Code:
In Python schreibt man alle Namen klein_mit_unterstrich, Ausnahmen sind Konstanten KOMPLETT_GROSS und Klassen in PascalCase-Schreibweise.
Auf Modulebene, der Code ohne EInrückungen, sollte kein ausführbarer Code stehen. Hier werden nur Konstanten, Funktionen, Klassen und der Einstiegpunkt in 'main' definiert. 'main' ist die Funktion, aus der das Programm gesteuert werden sollte. Hier könntest du deine Sensoren etc. definieren und dann an die Klasse übergeben.
Wenn du sprechende Namen verwendest, sparst du dir einige Kommentare.
'root.destroy()' wird nie aufgerufen, denn du verlässt die 'mainloop' nicht.
'self.vor_aktion' ist zwar mit Hilfe deines Kommentars nachvollziehbar, bzw. man versteht was du machen willst, aber im Laufe des Codes ist es nicht gerade selbstredent. Du könntest auch einfach mit Worten angeben, was die vorherige Aktion war.
Werte muss man in Pyhton nicht zwingend vorbelegen. Wenn man den Wert allerdings inerhalb der Klasse benötigt und nicht nur in einer Funktion einer Klasse, dann kann man Werte mit 'None' vorbelegen. 'self.PWMLI-wert' und 'self.PWMRe_wert' werden nur in Funktionen benötigt. Es wird nie der Wert, der daran gebunden wird abgefragt. Erst nach dem er in einer Funktion gesetzt wurde. Das heißt du benötigst kein 'self' und kannst den Namen in der Funktion definieren und verwenden.
In 'AbstandVorne' definierst du Namen und bindest sie an 'self'. Üblich ist es, dass diese Namen in der '__init__' definiert werden. Ist aber nicht nötig, da der vorherige Wert nicht relevant für dich ist und du immer den aktuellen brauchst. Weiter ist es auch nicht nötig, da du 'sensor_vorne.distance' direkt abfragen kannst. Die Skaliererei der Werte wird wohl Geschmackssache sein.
Die Steuerung der Leds würde ich in eine Funktion auslagern. Auch hier würde ich nicht immer hin und her rechnen, sondern einfach die Werte nehmen und anpassen.
Hier mal ein ungetesteter Zwischenstand:
#!/usr/bin/env/python3
import tkinter as tk
import gpiozero
import time
class Motorsteuerung(tk.Frame):
def __init__(
self,
master,
status_led,
motor_left,
motor_right,
distance_front,
distance_left,
distance_right,
distance_back,
led_left,
led_right,
):
tk.Frame.__init__(self, master)
self.pack()
self.status_led = status_led
self.motor_left = motor_left
self.motor_right = motor_right
self.distance_front = distance_front
self.distance_left = distance_left
self.distance_right = distance_right
self.distance_back = distance_back
self.led_right = led_right
self.led_left = led_left
self.previous_step = None
self.status_led.on()
self.measure_distance()
def controlling_leds(self):
while True:
if self.led_right.value > 0 and self.led_left.value > 0:
self.led_left.value -= 0.1
self.led_right.value -= 0.1
elif self.led_right.value == 0 and self.led_left.value == 0:
break
while True:
if self.led_right.value < 1 and self.led_left.value < 1:
self.led_left.value += 0.1
self.led_right.value += 0.1
elif self.led_right.value == 1 and self.led_left.value == 1:
break
def measure_distance(self):
while True:
if self.distance_front.distance >= 0.02:
print("vorne")
self.motor_forward()
elif self.distance_left.distance >= 0.01:
print("links")
self.motor_left()
def motor_forward(self):
if self.previous_step == "front":
self.led_left.value = self.led_right.value = 1
self.motor_right.forward()
self.motor_left.forward()
else:
self.controlling_leds()
self.motor_right.forward()
self.motor_left.forward()
self.previous_step = "front"
def motor_left(self):
if self.previous_step == "left":
self.led_left.value = self.led_right.value = 0.7
self.motor_right.forward()
self.motor_left.backward()
else:
self.controlling_leds()
self.motor_right.forward()
self.motor_left.backward()
self.previous_step = "left"
def main():
status_led = gpiozero.LED(23)
motor_left = gpiozero.Motor(forward=18, backward=15)
motor_right = gpiozero.Motor(forward=24, backward=25)
distance_front = gpiozero.DistanceSensor(echo=26, trigger=19, max_distance=5)
distance_left = gpiozero.DistanceSensor(echo=12, trigger=16, max_distance=5)
distance_right = gpiozero.DistanceSensor(echo=20, trigger=21, max_distance=5)
distance_back = gpiozero.DistanceSensor(echo=6, trigger=13, max_distance=5)
led_left = gpiozero.PWMLED(14)
led_right = gpiozero.PWMLED(8)
root = tk.Tk()
app = Motorsteuerung(
root,
status_led,
motor_left,
motor_right,
distance_front,
distance_left,
distance_right,
distance_back,
led_left,
led_right,
)
app.mainloop()
if __name__ == "__main__":
main()
Display More
Es fehlt noch einiges, aber du hast ja erwähnt das du noch nicht fertig bist.
Viel Erfolg
Dennis
Edit: Ob die Steuerung an sich so für dein Vorhaben sinnvoll ist und/oder genau genug musst du natürlich auch selbst über denken. Die Steuerung der Led's benötigt ja auch schon Zeit, in der sich das Objekt bewegt.
und wenn du laut Musik hörst
Kommt dann ganz auf die Musik an, bei Volksmusik rast das Auto automatisch gegen den nächsten Baum.
Hallo,
welche Programmiersprache und wie sieht der aktuelle Code aus?
Grüße
Dennis
Hallo,
der Code, der letztendlich den Text auf dem Display ändern soll ist dieser:
if __name__=='__main__':
epd = EPD_5in83_B()
epd.Clear(0xff, 0x00)
###648x480
epd.imageblack.fill(0xff)
epd.imagered.fill(0x00)
###
#Displayrand Anfang
epd.imageblack.text(vari0, 1, 1, 0x00)
#Mein Text
epd.imagered.text(vari1, 270, 75, 0xff)
epd.imagered.text(vari2, 270, 85, 0xff)
epd.imagered.text(vari2, 270, 95, 0xff)
epd.imagered.text(vari4, 270, 105, 0xff)
epd.imagered.text(vari5, 270, 115, 0xff)
epd.imagered.text(vari6, 270, 125, 0xff)
epd.imagered.text(vari7, 270, 135, 0xff)
epd.imagered.text(vari8, 270, 145, 0xff)
epd.imagered.text(vari9, 270, 155, 0xff)
epd.imagered.text(vari10, 270, 165, 0xff)
#Displyrande Ende
epd.imageblack.text(vari11, 600, 470, 0x00)
###
epd.display(epd.buffer_black, epd.buffer_red)
epd.delay_ms(6000)
Display More
Was soll deiner Meinung nach durch diesen Code auf dem Display passieren?
Ich frage deshalb, weil hier im Bruchteil von Sekunden 11 verschiedene Texte an das Display gesendet, dann noch zwei Bytearrays und dann wird etwas in den RAM geschrieben (das passiert in der Funktion 'display').
Schreib doch mal einen Text und mach dann eine Pause von zwei drei Sekunden (Stichwort 'sleep(2)') und dann den nächsten Text mit einer anderen Größe um zu sehen ob die sich ändert.
Ich bin mir auch nicht sicher ob die Zahlen, die du übergibst die Schriftgröße ist oder die Position wo der Text stehen soll. Denn diese Angabe fehlt mir irgendwie. Im Quelltext werden die zwei Argumente mit 'width' und 'height' bezeichnet. Hm daraus kann ich nicht sicher sagen, was es letztendlich ist.
Aber du hast das Display und kannst das mal versuchen.
Grüße
Dennis
Hallo,
'gpiozero' ist nicht in MicroPython verfügbar. Hier musst du mit 'machine' arbeiten.
https://docs.micropython.org/e…ickref.html#pins-and-gpio
MicroPython basiert auf der Syntax von Paython (3.4 glaube ich), also die Sprache wie du sie gelernt hast kannst du anwenden, es sind nur nicht alle Funktionen verfügbar. Da musst du dich dann etwas durch die Doku suchen.
Grüße
Dennis
Hallo,
schau mal noch mal die zweit letzt Zeile meines Codes an und dann deine Fehlermeldung. name vs. __name__.
Grüße
Dennis
Hallo,
hast du dir mal die Werte des Sensors ausgeben lassen? Bitte poste die vollständige Fehlermeldung.
'as' wird zum umbenennen verwendet, du nennst GPIO in GPIO um. In Python wird ausführbarer Code nur in Funktionen definiert. Verwende konstant 4 Leerzeichen zum einrücken. 'var1' und 'var2' sagen einem Leser leider nicht viel. Du kannst den Datentyp auch gleich bei der Temperaturabfrage ändern, dafür brauchst du nicht einen weiteren Namen verwenden.
Du erstellst in jedem Schleifendurchgang ein neues 'dhtDevice'-Objekt. Das würde man vor der Schleife einmal machen und dann damit in der Schleife arbeiten. Und wenn man schon dabei ist, in Python schreibt man Namen klein_mit_unterstrich. Ausnahmen sind Klassen in PascalCase-Schreibweise und Konstanten KOMPLETT_GROSS.
#!/usr/bin/env python3
import time
import board
import adafruit_dht
from RPi import GPIO
MAX_TEMPERATURE = 50
def main():
GPIO.setmode(GPIO.BCM)
GPIO.setup(9, GPIO.OUT)
dht_device = adafruit_dht.DHT11(board.D22)
while True:
temperature = int(dht_device.temperature)
if temperature < MAX_TEMPERATURE:
GPIO.output(9, True)
elif temperature > MAX_TEMPERATURE:
GPIO.output(9, False)
time.sleep(5)
if __name__ == '__main__':
main()
Display More
Hast du keine weitere Fehlermeldung erhalten? GPIO benötigt noch einen 'cleanup' Aufruf.
Grüße
Dennis
Hallo,
da wird einiges an Grundlagenwissen m.E. sogar übersprungen
wenn du die Programmiersprache lernen willst, dann könntest du das offizielle Tutorial dazu durcharbeiten:
https://docs.python.org/3/tutorial/
Wenn du etwas für eine bestimmte Anzahl machen willst, dann brauchst du eigentlich nicht unbedingt eine Dauerschleife, sondern du könntest eine Schleife verwenden, die eine bestimmte Anzahl an Durchläufen hat. In dem Fall wäre das eine for-Schleife mit der Funktion 'range'. Dadurch musst du selbst auch keinen Zähler mehr einabuen:
from gpiozero import LED
from time import sleep
led_blau = LED(3)
led_rot = LED(4)
for _ in range(20):
led_blau.on()
led_rot.off()
sleep(0.5)
led_blau.off()
led_rot.on()
sleep(0.5)
Display More
'range(20)' gibt in jedem Durchgang von 0 beginnend die Zahl erhöht um eins zurück, bis 20 Durchläufe um sind. Die Zahl wird an einen Namen gebunden. In meinem Beispiel ist der Name, der Unterstrich. Das verdeutlicht dem Leser, dass mit der Nummer im Code nichts weiter passiert. Will man im Code mit der Nummer aber auch noch was machen, dann ersetzt man den Unterstrich durch einen sprechenden Namen und kann ihn dann verwenden.
Grüße
Dennis
Hallo,
Bisher habe ich gehört, dass Stepmotor sinnvoller wären, da man damit besser Anfang und Ende steuern kann
der Vorteil ist, dass du in vielen Fällen um einen zusätzlichen Drehgeber drum herum kommst, dann die Schritte die der Schrittmotor macht gezählt werden können. Dann weist du wie weit sich der Motor gedreht hat. Das Problem für dein Anfang und Ende ist, dass dein Motor nicht weis wo das ist und auch nicht wo er selbst ist. Es werden nur Schritte gezählt.
Wenn dein Kabel ganz aufgewickelt ist und du schließt deine Schaltung an und weist das du 200 Schritte bis Ende fahren musst, dann ist das ok. Du bist bei Systemstart auf 0 Schritte und dann geht los. Was aber, wenn du irgendwo in der Mitte stehst, zum Beispiel wegen eines Stromausfalls? Dann weist du nicht mehr wie weit du hoch oder runter fahren musst.
Also es wird noch eine Referenz, bspw. ein Näherungsschalter, damit du irgendwie deine Position bestimmen kannst und bei Stromausfall eine Referenzfahrt machen kannst. Möglicherweise kannst du aber auch einen "normalen" Motor nehmen und einfach zwei Endlagenschalter um den Motor bei Anfang und Ende anzuhalten?
Grüße
Dennis
Hallo,
hier habe ich das mal detailliert und mit möglichst sprechende Namen, dass du siehst was gemacht wird, aufgeschrieben:
>>>arguments = '-c:(125,25,30)'
>>>arguments_without_letters = arguments.replace('-c:', '')
>>>print(arguments_without_letters)
(125,25,30)
>>>>without_clip = arguments_without_letters.replace('(', '').replace(')', '')
>>>>print(without_clip)
125,25,30
>>>>arguments_split_in_list = without_clip.split(',')
>>>>print(arguments_split_in_list)
['125', '25', '30']
>>>>list_with_int = []
>>>>for color in arguments_split_in_list:
list_with_int.append(int(color))
>>>>print(list_with_int)
[125, 25, 30]
>>>>print(type(list_with_int))
<class 'list'>
>>>>print(type(list_with_int[0]))
<class 'int'>
Display More
Und zusammengefasst im Code:
arguments = "-c:(125,25,30)"
colors = [int(color) for color in arguments.replace('-c:', '').replace('(', '').replace(')', '').split(',')]
print(colors)
print(type(colors[0]))
Grüße
Dennis
Hallo,
oder fehlt noch ein spezielle Parametrierung ?
du kannst die Zeitzonen auch angeben:
https://stackoverflow.com/ques…-get-correct-current-time
Was passiert mit :
ntptime.settime(timezone=2) ?
Grüße
Dennis
Hallo,
in einer Unterhaltung hat sich ergeben, dass die eingesetzen Encoder sehr oft Probleme mit prellen haben.
Hier habe ich mal eine stark vereinfachte Klasse geschrieben, die nur auf eine Flanke reagiert, keine Bitmuster abfragt und der du eine Entprellzeit mitgeben kannst.
from machine import Pin
from time import ticks_ms, ticks_diff
class Rotary:
def __init__(self, direction_pin, clock_pin, debounce_time):
self.direction_pin = Pin(direction_pin, Pin.IN, Pin.PULL_DOWN)
self.clock_pin = Pin(clock_pin, Pin.IN, Pin.PULL_DOWN)
self.debounce_time = debounce_time
self.timestamp = ticks_ms()
self.clock_pin.irq(handler=self.rotary_change, trigger=Pin.IRQ_FALLING)
self.counter = 0
def rotary_change(self, pin):
if ticks_diff(ticks_ms, self.timestamp) >= self.debounce_time:
self.counter += -1 if self.direction_pin.value() else 1
self.timestamp = ticks_ms()
Display More
Da dein Handler ja eigentlich auch nichts anderes macht als +1 oder -1 zu rechnen, habe ich darauf mal verzichtet.
Zum testen der Klasse, kannst du zum Beispiel sowas machen:
from utime import sleep
from Rotary import Rotary
def main():
# last Value for Rotary = debounce-time in ms
rotary = Rotary(16, 17, 10)
while True:
print(rotary.counter)
sleep(0.1)
if __name__ == "__main__":
main()
Display More
Die Klasse unter 'Rotary.py' speichern. In meinem Beispiel ist 16 der Clock-Pin, 17 der Direction-Pin und 10 ist die Entprellzeit in Millisekunden. Damit kannst du ja etwas spielen, bis alles so funktioniert wie du willst.
Könntest auch noch einen PWM-Pin definieren und Duty-Cycle abhängig vom Encoder laufen lassen und dann nochmal messen. Also sowas:
from utime import sleep
from Rotary import Rotary
from machine import Pin, PWM
PWM_PIN = 18
def main():
# last Value for Rotary = debounce-time in ms
rotary = Rotary(16, 17, 10)
pwm = PWM(Pin(PWM_PIN))
duty_cycle = 0
pwm.duty(duty_cycle)
while True:
duty_cycle = rotary.counter if rotary.counter >= 0 else 0
print(duty_cycle)
pwm.duty(duty_cycle)
sleep(0.5)
if __name__ == "__main__":
main()
Display More
Jeder Code ist ungetestet. Default-Wert für die Frequenz liegt (glaube ich) schon bei 5kHz, die müsste man nicht extra angeben.
Grüße
Dennis
Hallo,
Bernd666 ein Entprellen des Encoders kann ich in der Klasse nicht finden. Meiner Meinung nach wird lediglich der gesetzte Wert der Pins abgefragt und mit dem vorherigen Wert verglichen und je nach Zustand eine entsprechende Funktion aufgerufen.
Franky07 eventuell ist "deine" Klasse nicht robust genug gebaut und schedule hat nicht genügend Durchsetzungskraft um jeden Puls zeitgerecht durchzusetzen. Dazu findet man in der Doku auch soetwas:
QuoteDisplay MoreNote: If
schedule()
is called from a preempting IRQ, when memory
allocation is not allowed and the callback to be passed toschedule()
is
a bound method, passing this directly will fail. This is because creating a
reference to a bound method causes memory allocation. A solution is to
create a reference to the method in the class constructor and to pass that
reference toschedule()
. This is discussed in detail here
reference documentation under “Creation of Python
objects”.
Der ESP32 hat ja von Haus aus schon einen Pulse-Counter mit an Board, der ist also bestens dazu geeignet die Änderungen des Encoders zu zählen. Infos dazu findet man hier:
https://docs.espressif.com/pro…nce/peripherals/pcnt.html
Leider kannst du diese Funktion nicht in deiner MicroPython-Version finden.
Es wäre aber denoch interessant wie sich dein Encoder mit dieser Funktion verhalten würde. Glücklicherweise gibt es jemand, der genau diese Funktion in MicroPython implementiert hat. Dazu musst du allerdings diese Version nutzen:
https://github.com/deets/micropython/tree/mcpwm-and-encoder
Die Doku dazu:
https://github.com/deets/micro…kref.rst#pcnt-pin-counter
Und um die MicroPython-Version zu kompilieren:
https://github.com/bskp/microp…v-esp32-mcpwm/ports/esp32
Ich habe das vor einiger Zeit erfolgreich verwendet. Der ESP32 hatte damit auch keinerlei Probleme die Impulse einer 60kHz Frequenz zu zählen.
So, nur mal das du siehst, welche Möglichkeiten dir der ESP32 bietet. Ob das verwenden einer anderen MicroPython-Version zu aufwendig für ein Lernprojekt ist, kann ich nicht beurteilen. Aber ich denke die jetzt verwendete Klasse wird auch nur unbetrachtet im Hintergrund "stehen", dann könnte man auch den PCNT verwenden.
Grüße
Dennis
Edit: Weitere Infos und auch eine Alternative zu "deiner" Klasse ist unter folgendem Link zu finden:
Hallo,
nur mal ganz kurz: hast du den Encoder mal an andere GPIO's angeschlossen, weil 9, 10 und 11 sind laut hier nicht für Input geeignet.
Schau dir mal die Seite an, da gibts noch eine recht schöne Tabelle.
Grundsätzlich ist der ESP32 für sollche Aufgaben bestens geeignet.
Grüße
Dennis
Hallo,
in deinem Link sind ja einige Codebeispiele. Könntest du mal bitte den Code, den du auf dem ESP32 hast, hier posten? Am besten in Code-Tags (der </> - Button) dann bleiben die Einrückungen erhalten.
Grüße
Dennis
Hallo,
Warum hast du noch die 256 in 255 geändert?
Weil mit 256 der erste Schleifendurchgang 0 geben müsste und erst ab der zweiten Schleife werden die Zahlen von oben nach unten gezählt. Wenn ich 256 genommen hätte, dann hätte ich einen unschönen Sprung erwartet, wenn man die Schleife langsam laufen lässt.
Hab das aber selbst nicht testen können.
Du kannst ja mal die Werte ändern und dir die Werte, mit dem Rechenergebnis mit 'print' ausgeben lassen, dann siehst du was ich meine.
Schön das alles geklappt hat.
Grüße
Dennis
Hallo,
mal etwas Abwechslung für Zwischendurch
Alle Beispiele drehen im Uhrzeigersinn, nur der Rainbow.Cycle nicht. Kann man bei dem die Richtung tauschen?
Was passiert damit wenn du die Funktion so änderst:
def rainbowCycle(strip, wait_ms=20, iterations=5):
"""Draw rainbow that uniformly distributes itself across all pixels."""
for j in range(255 * iterations, 0, -1):
for i in range(strip.numPixels(), 0, -1):
strip.setPixelColor(i, wheel(
(int(i * 256 / strip.numPixels()) + j) & 255))
strip.show()
time.sleep(wait_ms / 1000.0)
Ich habe sowas noch nie angesteuert, aber das wäre mal meine erste Idee.
Grüße
Dennis
Nach dem Erkennen eines Magneten kommt das:
Ich hatte die falsche Exception verwendet
from gpiozero import DigitalInputDevice, LED
from time import monotonic, sleep
from math import pi
from threading import Thread
from functools import partial
LED_PIN = 17
SENSOR_PIN = 24
# in mm
TIRE_DIAMETER = 40
class SpeedGauge(Thread):
def __init__(self, hall_sensor, led):
super().__init__()
self.hall_sensor = hall_sensor
self.led = led
self.start = None
self.end = None
self.hall_sensor.when_deactivated = partial(self.get_time, "start")
self.hall_sensor.when_activated = partial(self.get_time, "end")
def get_time(self, position):
if position == "start":
self.start = monotonic()
self.led.on()
else:
self.end = monotonic()
self.led.off()
self.calculate_speed()
def calculate_speed(self):
try:
speed = (pi * TIRE_DIAMETER / 1000) / (self.end - self.start)
rpm = (speed / (pi * TIRE_DIAMETER)) * 60
print(f" Drehzahl: {speed} m/s, RPM: {rpm} 1/min")
except TypeError:
print('Waiting...')
def main():
led = LED(LED_PIN)
hall_sensor = DigitalInputDevice(SENSOR_PIN)
SpeedGauge(hall_sensor, led)
while True:
print("Jetzt kann man sonst noch was machen")
sleep(1)
print("Oder nochmal was")
sleep(1)
if __name__ == "__main__":
main()
Display More
Grüße
Dennis