- fchao-Sinus-Wechselrichter AliExpress         
Ergebnis 1 bis 4 von 4

Thema: Projekt Arm V1

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    06.04.2008
    Ort
    Rottenburg a.N.
    Alter
    41
    Beiträge
    94

    Projekt Arm V1

    Anzeige

    Praxistest und DIY Projekte
    Hi,

    wie in meinem letzten Thread https://www.roboternetz.de/phpBB2/viewtopic.php?t=48255 "versprochen", hier nun mein Thread zu meinem aktuellen RP6-Projekt.

    Ziel:
    Der RP6 soll mit einem Arm umgehen können.
    Er soll Ziele finden, diese packen und weg transportieren.

    Umsetzung:

    Nach anfänglichen Schwierigkeiten mit der Mechanik und Elektronik ist jetzt der erste Entwurf meines Roboterarms fertig geworden. Er benötigt noch sehr viel Nacharbeit, und ist deshalb z.zt. erst im Stadium des "Prototypings". Augenblicklich ist der RP6 allerdings noch auf menschliche Hilfe angewiesen.

    Hier nun mal die ersten Pics:
    Das "Getriebe" zur Übersetzung des doch etwas schwachen Servos (10 Ncm Stellmoment) für den Arm:

    Bild hier  

    Bild hier  

    Bild hier  


    der gesamte Greifarm:
    Bild hier  

    Bild hier  


    Der Greifer einzeln:

    Bild hier  

    Bild hier  


    Der montierte Greifarm am RP6:

    Bild hier  

    Bild hier  

    Bild hier  


    Er ist noch nicht ganz fertig, jedoch schon einsatzbereit.

    Funktion:
    Wenn es einmal klatscht (MicroPeak), dann
    - Fahre den Arm auf 0° und mache den Greifer auf
    - greife langsam nach einem Gegenstand, der dir gegeben wurde, bis die Taste 3 auf der M32 gedrückt wird.
    - fahre den Arm auf 45° hoch und lasse den Gegenstand nicht los.

    Das wars erstmal, ich bin aber noch dran...

    Wenn es Neuerungen gibt, werde ich diese posten.

    Gruß

    topgunfb
    Wer Interesse an Mangas hat, muss meine Website besuchen:
    http://www.manga-bl.de
    ---Bald auch mit RP6-Infos zu Projekten---

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    24.01.2008
    Ort
    Zürich
    Beiträge
    604
    Hi,

    darf man erfahren an welchen Pins du die Servos angeschlossen hast und mal deinen code sehen?

    würd mich nur mal interressieren xD

    LG Pr0gm4n

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    06.04.2008
    Ort
    Rottenburg a.N.
    Alter
    41
    Beiträge
    94
    Hi,

    die Pins sind PC2 und PC3 auf der M32.
    Der Code ist noch etwas "rückständig". Im Augenblick besteht er aus mehr Kommentar als aus Code, jedoch sollte das für einen geübten kein Problem sein.
    Als Basis habe ich die Lib von Dirk genommen, die er für 8 Servos komzipiert hat. Dort habe ich ein bisschen angepasst und rumgewerkelt.

    Hier also der code der Lib (RP6ControlServoLib.c):
    Code:
    /* ****************************************************************************
     *                           _______________________
     *                           \| RP6  ROBOT SYSTEM |/
     *                            \_-_-_-_-_-_-_-_-_-_/             >>> RP6 CONTROL
     * ----------------------------------------------------------------------------
     * ------------------------ [c]2008 - Dirk ------------------------------------
     * ****************************************************************************
     * File: RP6ControlServoLib.c
     * Version: 1.0
     * Target: RP6 CONTROL - ATMEGA32 @16.00MHz
     * Author(s): Dirk
     * ****************************************************************************
     * Description:
     * This is my simple RP6 Control Servo Library for up to 8 Servos.
     *
     * COMMENT: It is a good idea to use a separate power supply for the servos!
     *
     * Servo connections:
     *         SERVO1 -> I/O Pin 7 (IO_PC2)      SERVO5 -> I/O Pin 4 (IO_PC6)
     *         SERVO2 -> I/O Pin 5 (IO_PC3)      SERVO6 -> I/O Pin 1 (IO_PC7)
     *         SERVO3 -> I/O Pin 6 (IO_PC4)      SERVO7 -> I/O Pin 9 (IO_PD5)
     *         SERVO4 -> I/O Pin 3 (IO_PC5)      SERVO8 -> I/O Pin 8 (IO_PD6)
     *
     * ****************************************************************************
     * ATTENTION: Stopwatch 1 is used for the servo task! Please do
     *            not use this stopwatch elsewhere in your program!
     *
     * ****************************************************************************
     * THE CHANGELOG CAN BE FOUND AT THE END OF THIS FILE!
     * ****************************************************************************
     */
     
    /*****************************************************************************/
    // Includes:
    
    #include "RP6ControlServoLib.h"
    
    /*****************************************************************************/
    // Variables:
    
    uint8_t usedservos;
    uint8_t servo_on = FALSE;
    
    uint16_t impulselength1 = 0;
    uint16_t impulselength2 = 0;
    uint16_t impulselength3 = 0;
    uint16_t impulselength4 = 0;
    uint16_t impulselength5 = 0;
    uint16_t impulselength6 = 0;
    uint16_t impulselength7 = 0;
    uint16_t impulselength8 = 0;
    
    volatile uint16_t intcounter = 0;
    
    /*****************************************************************************/
    // Functions:
    
    /**
     * INIT SERVO
     *
     * Call this once before using the servo function.
     * Timer 1 is configured to work in "Clear Timer On
     * Compare Match Mode" (CTC). So no PWM is generated!
     * The timer runs on a fixed frequency (100kHz).
     *
     * Input:  Servos -> Used Servos
     *         Examples:
     *         - initSERVO(SERVO1 | SERVO2) -> Use only Servos 1 and 2
     *         - initSERVO(SERVO1 | SERVO6) -> Use only Servos 1 and 6
     *         - initSERVO(SERVO1 | SERVO2 | SERVO8) -> Use Servos 1, 2 and 8
     *
     */
    void initSERVO(uint8_t servos)
    {
       usedservos = servos;            // Save used Servos
       impulselength1 = 0;
       impulselength2 = 0;
       impulselength3 = 0;
       impulselength4 = 0;
       impulselength5 = 0;
       impulselength6 = 0;
       impulselength7 = 0;
       impulselength8 = 0;
       if (servos & SERVO1) {DDRC |= IO_PC2; PORTC &= ~IO_PC2;}
       if (servos & SERVO2) {DDRC |= IO_PC3; PORTC &= ~IO_PC3;}
       if (servos & SERVO3) {DDRC |= IO_PC4; PORTC &= ~IO_PC4;}
       if (servos & SERVO4) {DDRC |= IO_PC5; PORTC &= ~IO_PC5;}
       if (servos & SERVO5) {DDRC |= IO_PC6; PORTC &= ~IO_PC6;}
       if (servos & SERVO6) {DDRC |= IO_PC7; PORTC &= ~IO_PC7;}
       if (servos & SERVO7) {DDRD |= IO_PD5; PORTD &= ~IO_PD5;}
       if (servos & SERVO8) {DDRD |= IO_PD6; PORTD &= ~IO_PD6;}
    // -----------------------------------------------------------
    // Other possible ports for connecting Servos to RP6Control:
    //   if (servos & SERVOx) {DDRA |= ADC6; PORTA &= ~ADC6;}
    //   if (servos & SERVOx) {DDRA |= ADC7; PORTA &= ~ADC7;}
    // -----------------------------------------------------------
       cli();
       // Timer 1: Normal port operation, mode 4 (CTC), clk/8
       TCCR1A =  (0 << COM1A1)
             | (0 << COM1A0)
             | (0 << COM1B1)
             | (0 << COM1B0)
             | (0 << FOC1A)
             | (0 << FOC1B)
             | (0 << WGM11)
             | (0 << WGM10);
       TCCR1B =  (0 << ICNC1)
             | (0 << ICES1)
             | (0 << WGM13)
             | (1 << WGM12)
             | (0 << CS12)
             | (1 << CS11)
             | (0 << CS10);
       OCR1A = ((F_CPU/8/F_TIMER1)-1);   // 19 at 100kHz
    // ------------------------------------------------------
    // Possible OCR1A values (F_CPU = 16000000):
    //   OCR1A = 2000000 / F_TIMER1 - 1   // F_TIMER1  (Steps)
    //   OCR1A = 18;                  // 105263Hz  (9.5us)
    //   OCR1A = 19;                  // 100000Hz   (10us)
    //   OCR1A = 24;                  //  80000Hz (12.5us)
    //   OCR1A = 29;                  //  66667Hz   (15us)
    //   OCR1A = 34;                  //  57143Hz (17.5us)
    //   OCR1A = 39;                  //  50000Hz   (20us)
    // ------------------------------------------------------
       // Enable output compare A match interrupts:
       startSERVO();
       sei();
       startStopwatch1();               // Needed for 20ms pulse repetition
    }
    
    /**
     * START SERVO
     *
     * If the servo function was stopped with the
     * function stopSERVO() before, it can be
     * started again with this function.
     *
     */
    void startSERVO(void)
    {
       TIMSK |= (1 << OCIE1A);
       servo_on = TRUE;
    }
    
    /**
     * STOP SERVO
     *
     * The servo function uses a certain amount of the
     * processor's calculating time. If the Servos are
     * not moving for a while, the Timer 1 interrupt
     * can be stopped with this function.
     *
     */
    void stopSERVO(void)
    {
       TIMSK &= ~(1 << OCIE1A);
       servo_on = FALSE;
    }
    
    /**
     * PULSE SERVO
     *
     * This is the servo pulse generation. This function
     * must be called every 20ms (pulse repetition).
     *
     * position = 0               : Left touch
     * position = RIGHT_TOUCH     : Right touch
     * position = MIDDLE_POSITION : Middle position
     *
     * ! Please make sure in your main program, that the !
     * ! servo position values (servoX_position) don't   !
     * ! exceed RIGHT_TOUCH!!!                           !
     *
     * COMMENT: The pulses are only started here!
     *          The pulses end in the Timer 1 ISR!
     *
     */
    void pulseSERVO(void)
    {
       if (servo_on) {
          intcounter = RIGHT_TOUCH_ARM;      	// Avoid interference of Timer 1 ISR!
    										// (Only necessary, if pulseSERVO() is called
    										//  from outside of this library!)
          if (usedservos & SERVO1) {
             SERVO1_PULSE_ON; impulselength1 = LEFT_TOUCH_GREIFER + servo1_position;}
          if (usedservos & SERVO2) {
             SERVO2_PULSE_ON; impulselength2 = LEFT_TOUCH_ARM + servo2_position;}
          if (usedservos & SERVO3) {
             SERVO3_PULSE_ON; impulselength3 = LEFT_TOUCH + servo3_position;}
          if (usedservos & SERVO4) {
             SERVO4_PULSE_ON; impulselength4 = LEFT_TOUCH + servo4_position;}
          if (usedservos & SERVO5) {
             SERVO5_PULSE_ON; impulselength5 = LEFT_TOUCH + servo5_position;}
          if (usedservos & SERVO6) {
             SERVO6_PULSE_ON; impulselength6 = LEFT_TOUCH + servo6_position;}
          if (usedservos & SERVO7) {
             SERVO7_PULSE_ON; impulselength7 = LEFT_TOUCH + servo7_position;}
          if (usedservos & SERVO8) {
             SERVO8_PULSE_ON; impulselength8 = LEFT_TOUCH + servo8_position;}
          intcounter = 0;
       }
    }
    
    /**
     * TIMER1 ISR
     *
     * In this ISR the servo pulses are finished, if the
     * correct pulse length of each servo is reached.
     *
     */
    ISR (TIMER1_COMPA_vect)
    {
       intcounter++;
       if (intcounter == impulselength1) {SERVO1_PULSE_OFF;}
       if (intcounter == impulselength2) {SERVO2_PULSE_OFF;}
       if (intcounter == impulselength3) {SERVO3_PULSE_OFF;}
       if (intcounter == impulselength4) {SERVO4_PULSE_OFF;}
       if (intcounter == impulselength5) {SERVO5_PULSE_OFF;}
       if (intcounter == impulselength6) {SERVO6_PULSE_OFF;}
       if (intcounter == impulselength7) {SERVO7_PULSE_OFF;}
       if (intcounter == impulselength8) {SERVO8_PULSE_OFF;}
    }
    
    /**
     * SERVO TASK
     *
     * This is the servo task. The task performes the pulse repetition
     * with the help of a stopwatch.
     * At the next call of the servo task (earliest about 3ms after the
     * last servo pulse generation) the compare A match interrupt will
     * be disabled to reduce the interrupt load. It will be enabled
     * again after the next pulseSERVO() function call.
     *
     */
    void task_SERVO(void)
    {
       if (getStopwatch1() > 2) {TIMSK &= ~(1 << OCIE1A);}
       
       if (getStopwatch1() > PULSE_REPETITION_GREIFER) { // Pulse every ~20ms
          pulseSERVO();               // Servo pulse generation
          if (servo_on) {TIMSK |= (1 << OCIE1A);}
          setStopwatch1(0);
       }
      if (getStopwatch1() > PULSE_REPETITION_ARM) { // Pulse every ~20ms
          pulseSERVO();               // Servo pulse generation
          if (servo_on) {TIMSK |= (1 << OCIE1A);}
          setStopwatch1(0);
       }
    }
    
    /******************************************************************************
     * Additional info
     * ****************************************************************************
     * Changelog:
     * - v. 1.0 (initial release) 31.12.2008 by Dirk
     *
     * ****************************************************************************
     */
    
    /*****************************************************************************/
    // EOF
    Hier der Code der .h-Lib:
    Code:
    /* ****************************************************************************
     *                           _______________________
     *                           \| RP6  ROBOT SYSTEM |/
     *                            \_-_-_-_-_-_-_-_-_-_/             >>> RP6 CONTROL
     * ----------------------------------------------------------------------------
     * ------------------------ [c]2008 - Dirk ------------------------------------
     * ****************************************************************************
     * File: RP6ControlServoLib.h
     * Version: 1.0
     * Target: RP6 CONTROL - ATMEGA32 @16.00MHz
     * Author(s): Dirk
     * ****************************************************************************
     * Description:
     * This is the RP6ControlServoLib header file.
     * You have to include this file, if you want to use the library
     * RP6ControlServoLib.c in your own projects.
     *
     * ****************************************************************************
     * THE CHANGELOG CAN BE FOUND AT THE END OF THIS FILE!
     * ****************************************************************************
     */
     
    /*****************************************************************************/
    // Includes:
    
    #include "RP6ControlLib.h"       // The RP6 Control Library.
                            // Always needs to be included!
    
    /*****************************************************************************/
    // Defines:
    
    // Servo constants:
    #define SERVO1            0b00000001
    #define SERVO2            0b00000010
    #define SERVO3            0b00000100
    #define SERVO4            0b00001000
    #define SERVO5            0b00010000
    #define SERVO6            0b00100000
    #define SERVO7            0b01000000
    #define SERVO8            0b10000000
    
    // Servo movement limits (depending on servo type):
    // Standard Servos need an impulse every 20ms (50Hz). This impulse must have
    // a length of 1ms (0.7 .. 1ms) to move the servo lever to the left touch
    // and a length of 2ms (2 .. 2.3ms) for moving it to the right touch. In the
    // middle position the servo needs an impulse length of 1.5ms (1.3 .. 1.6ms).
    // If you want to modify the following constants for a certain servo type,
    // you must adapt the LEFT_TOUCH constant first (values ~70 .. 100 = ~0.7 ..
    // 1ms at 100kHz) by using a servo position value (servoX_position) of zero.
    // After that you have two "screws" to adjust the servo movement limits:
    // First you may change the RIGHT_TOUCH constant. If you choose a higher
    // value than 255, you will use 16-bit values. Higher values mean a longer
    // impulse length, but longer impulses than 2.3ms do not make sense.
    // Second you may alter the Timer 1 frequency constant (F_TIMER1).
    // A higher frequency leads to smaller steps of the servo movement. This of
    // course reduces the impulse length and may be compensated again by a higher
    // RIGHT_TOUCH constant. As a possible range of Timer 1 frequency values you
    // may use 50kHz (20us) .. 105.263kHz (9.5us).
    // HINT: If you alter F_TIMER1, you'll have to adapt LEFT_TOUCH and
    //       RIGHT_TOUCH again as you can see in the following table!
    //     Steps ->      9.5      10      12.5   15      17.5   20    [us]
    //  ------------------------------------------------------------------
    //  LEFT_TOUCH      74      71      57      47      41      35
    //  RIGHT_TOUCH      169      162      129      107      92      80
    //  F_TIMER1      105263   100000   80000   66667   57143   50000 [Hz]
    #define LEFT_TOUCH         41         					// Left servo touch      (~0.7ms)
    #define RIGHT_TOUCH         100        					// Right servo touch     (~2.3ms)
    #define MIDDLE_POSITION      (RIGHT_TOUCH / 2) 			// Middle position (~1.5ms)
    #define PULSE_REPETITION   15         					// Pulse repetition freq. (~50Hz)
    #define F_TIMER1         66667      					// Timer 1 frequency     (100kHz)
    
    #define LEFT_TOUCH_ARM             70        			// Left servo touch      (~0.7ms)
    #define RIGHT_TOUCH_ARM            70        			// Right servo touch     (~2.3ms)
    #define MIDDLE_POSITION_ARM        (RIGHT_TOUCH / 2) 	// Middle position (~1.5ms)
    #define PULSE_REPETITION_ARM       17.5	         		// Pulse repetition freq. (~50Hz)
    #define F_TIMER1_ARM               66667      			// Timer 1 frequency     (100kHz)
    
    #define LEFT_TOUCH_GREIFER         105        			// Left servo touch      (~0.7ms)
    #define RIGHT_TOUCH_GREIFER        60	      			// Right servo touch     (~2.3ms)
    #define MIDDLE_POSITION_GREIFER    (RIGHT_TOUCH / 2) 	// Middle position (~1.5ms)
    #define PULSE_REPETITION_GREIFER   17.5         		// Pulse repetition freq. (~50Hz)
    #define F_TIMER1_GREIFER           66667      			// Timer 1 frequency     (100kHz)
    
    
    // Servo ports:
    #define SERVO1_PULSE_ON      (PORTC |= IO_PC2)   // PC2
    #define SERVO1_PULSE_OFF   (PORTC &= ~IO_PC2)
    #define SERVO2_PULSE_ON      (PORTC |= IO_PC3)   // PC3
    #define SERVO2_PULSE_OFF   (PORTC &= ~IO_PC3)
    #define SERVO3_PULSE_ON      (PORTC |= IO_PC4)   // PC4
    #define SERVO3_PULSE_OFF   (PORTC &= ~IO_PC4)
    #define SERVO4_PULSE_ON      (PORTC |= IO_PC5)   // PC5
    #define SERVO4_PULSE_OFF   (PORTC &= ~IO_PC5)
    #define SERVO5_PULSE_ON      (PORTC |= IO_PC6)   // PC6
    #define SERVO5_PULSE_OFF   (PORTC &= ~IO_PC6)
    #define SERVO6_PULSE_ON      (PORTC |= IO_PC7)   // PC7
    #define SERVO6_PULSE_OFF   (PORTC &= ~IO_PC7)
    #define SERVO7_PULSE_ON      (PORTD |= IO_PD5)   // PD5
    #define SERVO7_PULSE_OFF   (PORTD &= ~IO_PD5)
    #define SERVO8_PULSE_ON      (PORTD |= IO_PD6)   // PD6
    #define SERVO8_PULSE_OFF   (PORTD &= ~IO_PD6)
    // -----------------------------------------------------------
    // Other possible ports for connecting Servos to RP6Control:
    //#define SERVOx_PULSE_ON      (PORTA |= ADC6)      // PA6
    //#define SERVOx_PULSE_OFF   (PORTA &= ~ADC6)
    //#define SERVOx_PULSE_ON      (PORTA |= ADC7)      // PA7
    //#define SERVOx_PULSE_OFF   (PORTA &= ~ADC7)
    // -----------------------------------------------------------
    
    /*****************************************************************************/
    // Variables:
    
    uint16_t servo1_position;      // Servo 1 position [0..RIGHT_TOUCH]
    uint16_t servo2_position;      // Servo 2 position [0..RIGHT_TOUCH]
    uint16_t servo3_position;      // Servo 3 position [0..RIGHT_TOUCH]
    uint16_t servo4_position;      // Servo 4 position [0..RIGHT_TOUCH]
    uint16_t servo5_position;      // Servo 5 position [0..RIGHT_TOUCH]
    uint16_t servo6_position;      // Servo 6 position [0..RIGHT_TOUCH]
    uint16_t servo7_position;      // Servo 7 position [0..RIGHT_TOUCH]
    uint16_t servo8_position;      // Servo 8 position [0..RIGHT_TOUCH]
    
    /*****************************************************************************/
    // Functions:
    
    void initSERVO(uint8_t servos);
    void startSERVO(void);
    void stopSERVO(void);
    void pulseSERVO(void);
    void task_SERVO(void);
    
    /******************************************************************************
     * Additional info
     * ****************************************************************************
     * Changelog:
     * - v. 1.0 (initial release) 31.12.2008 by Dirk
     *
     * ****************************************************************************
     */
    
    /*****************************************************************************/
    // EOF
    Und hier nun der Entwurf meines Programmes:
    Code:
    #include "RP6ControlServoLib.h"
    #include "RP6ControlLib.h"
    
    uint16_t pos_ARM = 0;
    uint16_t pos_GREIFER = 0;
    
    
    int main(void)
    { 
       
       initRP6Control();
       initLCD();
    //##########################
       initSERVO(SERVO1 | SERVO2);
       startStopwatch2();
    	dischargePeakDetector();
    	
    	uint16_t last_peak = 0;
    	uint8_t peak_counter = 0;
    	while(true) 
    	{
    		// Measure last Microphone peak:
    		uint16_t tmp = getMicrophonePeak();
    		// show last value on LCD:
    		//setCursorPosLCD(0, 3); 
    		//writeIntegerLengthLCD( tmp, DEC, 4);
    		if(tmp > 4) 
    		{
    			if(tmp > last_peak) // Do we have a new peak?
    			{
    				last_peak = tmp;
    				peak_counter = 0;
    			}
    			if(last_peak >= 62)
    			{
    		setStopwatch2(0);
    		pos_ARM = 50; 			// 0°->5; ~45°->50;
    		pos_GREIFER = 5;		// geschlossen->5;  offen->65;
    		servo1_position = pos_GREIFER;
    		servo2_position = pos_ARM;  
    		task_SERVO();
    
    		// 4= Arm runter auf "5", Greifer ganz auf und langsam zu bis Taste 3;
    		// 3= Position des Greifers halten und Arm hoch;
    
    
    		
    		clearLCD();
    		setCursorPosLCD(0, 0);
             writeStringLCD_P("ARM:");
             writeIntegerLCD(pos_ARM, DEC);
             setCursorPosLCD(1, 0);
    		 writeStringLCD_P("Greifer: ");
    		 writeIntegerLCD(pos_GREIFER, DEC);
    		setStopwatch2(0);
    		pos_ARM = 5;
    		pos_GREIFER = 65;
    		servo1_position = pos_GREIFER;
    		servo2_position = pos_ARM;  
    		uint16_t i = 0;
    		
    		while(i++ < 20)
    		{
    			task_SERVO();
    			mSleep(50);
    		}
    				
    		while(getPressedKeyNumber() != 3 && pos_GREIFER > 5)
    		{
    		 setStopwatch2(0);
    		 pos_GREIFER -=1;
             servo1_position = pos_GREIFER;
    		 task_SERVO();
    		 mSleep(50);
    		}
    	
    		while(i++ < 200)
    		{
    		 setStopwatch2(0);
    		 pos_ARM = 50;
             servo2_position = pos_ARM;
    		 task_SERVO();
    		 mSleep(3);
    		}
    	
    		while(true)
    		{task_SERVO();
    		mSleep(30);
    		}
    	  //mSleep(3);
    }
     }}}
    Das Programm ist noch lange nicht fertig, aber wie oben beschrieben, bereits tauglich für eine Prototyping-Phase.

    Gruß

    topgunfb
    Wer Interesse an Mangas hat, muss meine Website besuchen:
    http://www.manga-bl.de
    ---Bald auch mit RP6-Infos zu Projekten---

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    24.01.2008
    Ort
    Zürich
    Beiträge
    604
    achso danke!

    LG Pr0gm4n

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress