Hallo,
der ASD1015 ist angekommen und funktioniert einwandfrei. Jetzt ist meine Anzeige stabil. Vielen Dank für den Hinweis.
Leider hat sich jetzt noch ein anderes Problem eingeschlichen. Ich kann einstellen um wieviel Grad sich die Schweißachse drehen soll. Wenn das Schweißgerät aus ist, soll sich die Schweißachse aber wieder auf 0° bzw. 360° drehen, damit man das Werkstück angenehmer entnehmen kann. Das hat bis heute auch funktioniert und funktioniert jetzt nur noch zufällig.
Ich habe mir die Werte der aktuellen Position ausgeben lassen und teilweise fehlen in paar und dann dreht der Motor ununterbrochen im Kreis. Kann dass sein dass der I2C-Bus jetzt irgendwelche Ressourcen benötigt und mir dadurch mein Prozess stört?
Die Funktion, die den Motor stoppen soll wäre diese:
Code: Alles auswählen
def stop_welding(self, stop_to_initial=False):
self.welding_axis.duty(0)
self.welding_machine.off()
sleep(1)
if not stop_to_initial and self.actually_welding_position != 360:
self.welding_axis.duty(-60 * self.direction)
while True:
if self.actually_welding_position in [360, 0]:
self.welding_axis.duty(0)
break
self.counter.reset()
Die ganze 'main.py':
Code: Alles auswählen
from time import sleep, ticks_diff, ticks_us
from esp32 import MCPWM, PCNT
from LargeCounter import LargeCounter
from machine import ADC, Pin, I2C
from ControlDisplay import Display
from ads import ADS1015
import _thread
RX_PIN = 34
TX_PIN = 13
ENCODER_PINS = [2, 15]
REFERENCE_SWITCH_PIN = 4
END_POSITION_PINS = {"left": 18, "right": 19}
AUTOMATIC_BUTTON_PIN = 35
SIMULATE_BUTTON_PIN = 33
START_BUTTON_PIN = 14
ROTATE_BUTTON_PIN = 39
SDA = 21
SCL = 22
STATUS_LED_PIN = 32
WELDING_MACHINE_PIN = 26
PNEUMATIC_CYLINDER_PINS = {"left": 25, "right": 27}
PWM_PINS = {"welding_axis": [5, 16], "rotation_axis": [17, 23]}
ENCODER_RESOLUTION = 5000
# Welding-angle in °, speed in %, time before start welding in s
MAX_VALUES_TO_TRANSLATE_DIGITAL_VALUE = [550, 100, 5]
POSITION_MACHINE_START = "left"
RATIO = 152 / 63
# For example 5e6 = 5 seconds
APPLY_POSITION = 3e6
class WeldingControl:
def __init__(self):
self.display = Display(TX_PIN, RX_PIN)
i2c = I2C(0, sda=Pin(SDA), scl=Pin(SCL))
self.turn_switches = ADS1015(i2c, gain=1)
self.start = Pin(START_BUTTON_PIN, Pin.IN, Pin.PULL_DOWN)
self.rotate_workpiece = Pin(ROTATE_BUTTON_PIN, Pin.IN, Pin.PULL_DOWN)
self.simulate_mode = Pin(SIMULATE_BUTTON_PIN, Pin.IN, Pin.PULL_DOWN)
self.automatic_mode = Pin(AUTOMATIC_BUTTON_PIN, Pin.IN, Pin.PULL_DOWN)
self.welding_axis = MCPWM(0)
self.welding_axis.bind(
Pin(PWM_PINS["welding_axis"][0]), Pin(PWM_PINS["welding_axis"][1])
)
self.turning_axis = MCPWM(3)
self.turning_axis.bind(
Pin(PWM_PINS["rotation_axis"][0]), Pin(PWM_PINS["rotation_axis"][1])
)
self.welding_machine = Pin(WELDING_MACHINE_PIN, Pin.OUT)
self.cylinders = {
position: Pin(pin, Pin.OUT)
for position, pin in PNEUMATIC_CYLINDER_PINS.items()
}
self.status_led = Pin(STATUS_LED_PIN, Pin.OUT)
self.machine_start_reference = Pin(
REFERENCE_SWITCH_PIN, Pin.IN, Pin.PULL_DOWN
)
self.end_positions = {
position: Pin(END_POSITION_PINS[position], Pin.IN)
for position in END_POSITION_PINS
}
encoder = PCNT(0, Pin(ENCODER_PINS[0]), Pin(ENCODER_PINS[1]))
self.counter = LargeCounter(encoder)
try:
self.active_end_position = [
position
for position in self.end_positions
if self.end_positions[position].value()
][0]
except IndexError:
self.active_end_position = None
self.welding_axis.duty(0)
self.status_led.off()
for cylinder in self.cylinders.values():
cylinder.off()
sleep(1)
@property
def actually_welding_position(self):
# position in angle
return (
self.direction * 360 * self.counter.counter() // ENCODER_RESOLUTION // RATIO
)
@property
def direction(self):
return 1 if self.active_end_position == POSITION_MACHINE_START else -1
@property
def time_before_start(self):
return self.translate_measure_value(
self.turn_switches.read(channel1=1),
MAX_VALUES_TO_TRANSLATE_DIGITAL_VALUE[2],
)
@property
def welding_angle(self):
return self.translate_measure_value(
self.turn_switches.read(channel1=2),
MAX_VALUES_TO_TRANSLATE_DIGITAL_VALUE[0],
)
@property
def welding_speed(self):
return self.translate_measure_value(
self.turn_switches.read(channel1=0),
MAX_VALUES_TO_TRANSLATE_DIGITAL_VALUE[1] * self.direction,
)
@staticmethod
def translate_measure_value(value, reference_value):
# 1610 = max. value ads1015.read()
# Weldingspeed could be negative because of direction
value = max(value, 0)
if abs(reference_value) > 10:
return reference_value * value // 1610
else:
return round(reference_value * value / 1610, 1)
def check_machine_position(self):
self.turning_axis.duty(50)
if self.end_positions[POSITION_MACHINE_START].value():
self.turning_axis.duty(0)
self.active_end_position = POSITION_MACHINE_START
return True
def control_cylinder(self, state, position):
if state == "out":
self.cylinders[position].on()
else:
self.cylinders[position].off()
def control_welding_process(self):
self.status_led.off()
welding_success = self.do_welding()
if welding_success:
self.stop_welding()
if self.automatic_mode.value():
self.control_workpiece_rotation()
sleep(1)
welding_success = self.do_welding()
if welding_success:
self.stop_welding()
self.control_workpiece_rotation()
self.status_led.on()
def control_workpiece_rotation(self):
self.control_cylinder("in", self.active_end_position)
sleep(1)
self.rotate()
sleep(1)
self.control_cylinder("out", self.active_end_position)
def do_welding(self):
if not self.end_positions[self.active_end_position].value():
self.stop_welding(stop_to_initial=True)
self.set_back_to_initial_mode()
return False
if not self.simulate_mode.value():
self.welding_machine.on()
start = ticks_us()
while True:
if not self.end_positions[self.active_end_position].value():
self.stop_welding(stop_to_initial=True)
self.set_back_to_initial_mode()
return False
if ticks_diff(ticks_us(), start) > self.time_before_start * 1e6:
break
sleep(0.01)
self.welding_axis.duty(self.welding_speed)
while True:
if not self.end_positions[self.active_end_position].value():
self.stop_welding(stop_to_initial=True)
self.set_back_to_initial_mode()
return False
if self.actually_welding_position >= self.welding_angle:
break
self.welding_axis.duty(self.welding_speed)
sleep(0.01)
return True
def initial_machine(self):
if self.active_end_position is None:
self.control_cylinder("in", "left")
self.control_cylinder("in", "right")
sleep(1)
while True:
if self.check_machine_position():
sleep(0.5)
self.control_cylinder("out", self.active_end_position)
sleep(1)
break
sleep(0.1)
else:
self.control_cylinder("out", self.active_end_position)
while not self.initial_welding_axis():
pass
def initial_welding_axis(self):
initial_status = None
self.welding_axis.duty(100)
while True:
if self.machine_start_reference.value():
self.welding_axis.duty(0)
self.display.show_info_text(
"Position ändern: Start drücken --- Position bestätigen: Start 3s gedrückt halten")
while True:
if self.start.value():
timestamp = ticks_us()
while self.start.value():
time_delta = ticks_diff(ticks_us(), timestamp)
if time_delta >= APPLY_POSITION:
initial_status = True
self.display.show_info_text("Maschine ist einsatzbereit")
break
# Show text only if user held the button, not if just pressed shortly
if time_delta > 5e5:
self.display.show_info_text(
"Verbleibende Zeit: {:.1f}s".format((APPLY_POSITION - time_delta) * 1e-6))
if initial_status:
self.counter.reset()
return True
else:
self.display.show_info_text(
"Position ändern: Start drücken --- Position bestätigen: Start 3s gedrückt halten")
self.welding_axis.duty(80)
sleep(0.5)
while True:
if self.machine_start_reference.value():
self.welding_axis.duty(0)
initial_status = False
break
sleep(0.01)
def monitor_input_devices(self):
while True:
try:
if not self.end_positions[self.active_end_position].value():
self.set_back_to_initial_mode()
except KeyError:
pass
if self.simulate_mode.value():
self.welding_machine.off()
if self.start.value():
self.switching_start_stop()
if self.rotate_workpiece.value() and self.status_led.value():
self.display.show_info_text("Vorsicht Maschine dreht sich")
self.status_led.off()
self.control_workpiece_rotation()
sleep(1)
self.status_led.on()
self.show_info_text()
sleep(0.1)
def rotate(self):
for end_position in self.end_positions:
if self.active_end_position != end_position:
break
self.turning_axis.duty(
50 if self.active_end_position == POSITION_MACHINE_START else -50
)
sleep(1)
while True:
if self.end_positions[end_position].value():
self.turning_axis.duty(0)
self.active_end_position = end_position
break
sleep(0.1)
def set_back_to_initial_mode(self):
self.display.show_info_text("Positionsfehler. Start-Button für erneute Referenzfahrt drücken.")
self.status_led.off()
self.cylinders[self.active_end_position].off()
self.active_end_position = None
self.wait_for_initial()
self.initial_machine()
def show_info_text(self):
if self.simulate_mode.value():
simulate = "Simulationsmodus ist AN"
else:
simulate = "Simulationsmodus ist AUS"
if self.automatic_mode.value():
automatic = "Automatikmodus ist AN"
else:
automatic = "Automatikmodus ist AUS"
self.display.show_info_text("{} - {}".format(simulate, automatic))
def stop_welding(self, stop_to_initial=False):
self.welding_axis.duty(0)
self.welding_machine.off()
sleep(1)
if not stop_to_initial and self.actually_welding_position != 360:
self.welding_axis.duty(-60 * self.direction)
while True:
if self.actually_welding_position in [360.0, 0.0]:
self.welding_axis.duty(0)
break
self.counter.reset()
def switching_start_stop(self):
if not self.status_led.value():
self.stop_welding()
self.status_led.on()
else:
self.control_welding_process()
def update_display(self):
while True:
self.display.update_controller(
{'speed': self.welding_speed, 'time': self.time_before_start, 'angle': self.welding_angle})
sleep(0.1)
def wait_for_initial(self):
while not self.start.value():
sleep(0.1)
def main():
welding_control = WeldingControl()
welding_control.display.show_info_text("Start drücken für Referenzfahrt")
welding_control.wait_for_initial()
welding_control.display.show_info_text("Maschine wird vorbereitet")
welding_control.initial_machine()
_thread.start_new_thread(welding_control.update_display, ())
welding_control.status_led.on()
while welding_control.start.value():
pass
welding_control.monitor_input_devices()
if __name__ == "__main__":
main()
Die Bibliothek für den ASD1015 wäre
diese.
Weil ich es glaub hier noch nicht gezeigt habe, auf jeden Fall die entgütige Version noch nicht, hier ist meine ControlDisplay.py:
Code: Alles auswählen
from Nextion import Nextion
NUMBER_OF_PICTURES = 25
CONTROLLER_TO_PICTURE_SETTINGS = {
"speed": {
"add_to_picture_number": 0,
"max_value": 100,
"start_picture_number": 1,
"picture_position_x": 0,
"picture_position_y": 230,
"text_position": 80
},
"time": {
"add_to_picture_number": 25,
"max_value": 5,
"start_picture_number": 26,
"picture_position_y": 230,
"picture_position_x": 267,
"text_position": 340
},
"angle": {
"add_to_picture_number": 50,
"max_value": 550,
"start_picture_number": 51,
"picture_position_y": 219,
"picture_position_x": 529,
"text_position": 605
},
}
class Display:
def __init__(self, tx_pin, rx_pin):
self.display = Nextion(tx_pin, rx_pin, 9600)
self.last_values = {}
self.last_picture_number = {}
def update_controller(self, values):
for controller, factors in CONTROLLER_TO_PICTURE_SETTINGS.items():
value = abs(values[controller])
if value != self.last_values.get(controller):
picture_number = translate_to_picture_number(factors, value)
if picture_number != self.last_picture_number.get(controller):
self.display.cmd(
"pic {},{},{}".format(factors["picture_position_x"],factors["picture_position_y"], picture_number)
)
self.last_picture_number[controller] = picture_number
self.display.cmd('xstr {},300,114,60,1,65535,0,1,1,0,"{}"'.format(factors["text_position"], value))
self.last_values[controller] = value
def show_info_text(self, text):
self.display.cmd('xstr 8,167,770,43,2,65535,0,1,1,0,"{}"'.format(text))
def translate_to_picture_number(factors, value):
picture_number = factors["add_to_picture_number"] + (
NUMBER_OF_PICTURES * value // factors["max_value"]
)
return max(int(picture_number), factors["start_picture_number"])
Mit "KiCAD" habe ich heute morgen schon angefangen und mache nachher weiter. Bis jetzt kann ich aber noch nicht sagen, was ich nachher entgültig verwende.
Grüße
Dennis