Samstag, 16. Juni 2012

Selbstbau eines mikrocontroller gesteuerten Wiegenmotors

Das Video unten zeigt den Motor an der Wiege meines Sohnes in Aktion. Das Seil wurde mittlerweile durch eine Schubstange ersetzt :)

Die Geschwingigkeit des Getriebemotors kann durch einen Drehschalter stufenlos zwichen 23 und 43 Umdrehungen in der Minute geregelt werden. Es besteht die Möglichkeit zwischen Vorwärts- und Rückwärtslauf umzuschalten. Darüberhinaus stehen 3 automatische Programmaubläufe zur Verfügung:
1. langsames Beschleunigen, langsames Abbremsen, langsames Beschleunigen, usw.
2. hohe Drehzahl, Pause, niedrige Drehzahl, Pause, usw..
3. mittlerere Drehzahl vorwärts, mittlere Drehzahl rückwärts, mittlere Drehzahl vorwärts, usw.
Die Vorderansicht des Wiegenmotors:
 Detailansicht des LCD-Moduls:
Übersichtsbild aller Komponenten:
Der Schaltplan:

Der Programmcode:
******************************************************************************
'*
'* Programm Titel: cradle_motor_v11.bas
'* Compiler: BASCOM-AVR v1.11.9.0
'* Processor: Atmel ATmega8
'* Programm Funktion: Ansteuerung eines Getriebemotors durch PWM
'*
'******************************************************************************
'*
'* benutzt wird ein serieller Programmer (ISP - In-System-Programmer)
$regfile = "m8def.dat"
$crystal = 4000000                                          'interner Quarz 4 MHz

' LCD initialisieren
Config Lcdpin = Pin , Db4 = Portd.5 , Db5 = Portd.6 , Db6 = Portd.7 , Db7 = Portb.0 , E = Portd.1 , Rs = Portd.4
Config Lcd = 16 * 1
Cursor Off Noblink

' Timer1 für PWM initialisieren
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1
Config Portb.1 = Output
Pwm_out Alias Ocr1al

'ADC initialisieren
Config Adc = Single , Prescaler = Auto , Reference = Avcc
Start Adc

'Logikausgänge für LD293D definieren
Config Portc.1 = Output                                     'PIN 24 an 1A
Config Portc.2 = Output                                     'PIN 25 an 2A

'Drehrichtungsschalter, Programmfreigabeschalter und Programmwahltaste definieren
Direction_switch Alias Pinc.3
Program_switch Alias Pind.2
Mode_button Alias PinD.3
Config Direction_switch = Input                              'PIN 26
Config Program_switch = Input                               'PIN 4 (Int0)
Config Mode_button = Input                                  'PIN 5 (Int1)
Portc.3 = 1                                                            'interne pull up Widerstande setzen
Portd.2 = 1
Portd.3 = 1

'externe Interruts konfigurieren
Config Int0 = Rising                           'INT0 wird ausgelöst, wenn auf 'Program disable' umgeschaltet wird
Config Int1 = Low Level                    'INT1 wird ausgelöst, wenn Mode_button gedrückt wird
On Int0 Disable_program_mode
On Int1 Set_program
Enable Int0                                                 'externe INTs einschalten
Enable Int1
Enable Interrupts

'Unterprogramme definieren
Declare Sub Motor_forward()
Declare Sub Motor_backward()
Declare Sub Motor_break()
Declare Sub Lcd_out()
Declare Sub Set_pwm_out_from_adc()
Declare Sub Prog1()
Declare Sub Prog2()
Declare Sub Prog3()

'Variablen definieren
Dim RPM_Byte As Byte
Dim RPM_Word As Word
Dim RPM_Single As Single
Dim Enable_program_mode As Bit
Dim Program_mode As Byte
Dim I As Byte

'Variablen initialisieren
RPM_Byte = 0
Pwm_out = 0
Motor_forward
Program_mode = 0                                            'Manueller Modus



'Hauptprogramm
Do

   Debounce Direction_switch , 1 , Motor_forward , Sub      'direction_switch abfragen
   Debounce Direction_switch , 0 , Motor_backward , Sub


   Set_pwm_out_from_adc                         'Pulsbreite des Ausgangssignals setzen

   Lcd_out                                                  'Umdrehungen/Minute und Programmodus auf LCD ausgeben

   Select Case Program_mode                    'automatischen Programmablauf auswählen
      Case 1 : Prog1
      Case 2 : Prog2
      Case 3 : Prog3
   End Select
Loop
End



'LD293D Logikpegel für Vorwärtsdrehrichtung setzen
Sub Motor_forward()
Portc.1 = 0
portC.2 = 1
End Sub

'LD293D Logikpegel für Rückwärtsdrehrichtung setzen
Sub Motor_backward()
Portc.1 = 1
portC.2 = 0
End Sub

'LD293D Logikpegel für Bremsen (Kurzschluß des Motors) setzen
Sub Motor_break()
Portc.1 = 1
portC.2 = 1
End Sub

'Ausgaberoutine des LCD Displays
Sub Lcd_out()
   RPM_Byte = Pwm_out
   Rpm_single = Rpm_byte * 16                    'linear skalieren
   Rpm_single = Rpm_single / 200
   Rpm_byte = Rpm_single + 23

   Locate 1 , 1                                             'Pulsbreiten <10 werden als 0 Umdrehungen/Minute angezeigt
   If Pwm_out < 10 Then
      Lcd "RPM:  00"
   Else
      If Portc.1 = 0 Then                                'erste Zeile = Umdrehungen/Minute
         Lcd "RPM: +" ; Rpm_byte
      Else
         Lcd "RPM: -" ; Rpm_byte
      End If
   End If

   Locate 2 , 1                                             'zweite Zeile = Anzeige des Programms
   If Program_mode = 0 Then
      Lcd "Mode: --"
   Else
      Lcd "Mode: 0" ; Program_mode
   End If
End Sub

'Pulsbreite manuell setzen
Sub Set_pwm_out_from_adc()
   RPM_Word = Getadc(0)                                 
   Rpm_single = Rpm_word * 255                              'ADC Wert in Pulsbreitensignal umrechnen
   RPM_Single = RPM_Single / 1023
   Pwm_out = RPM_Single
End Sub

'Programmzähler setzen
Set_program:
If Program_mode < 3 And Program_switch = 0 Then        'Hochzählen wenn Mode_button gedrückt wurde
   Program_mode = Program_mode + 1
   Disable Int1                                                                    'Mode_button entprellen
   Waitms 300
   Enable Int1
End If
Return

'Automatikmodus beenden
Disable_program_mode:
Program_mode = 0                                            'Programmzähler auf 0 setzen
Disable Int0                                                        'Program_switch entprellen
Waitms 300
Enable Int0
Return

'automatischer Programmablauf 1
Sub Prog1()
Motor_break                                                 'langsam Beschleunigen, langsam Abbremsen, langsam Beschleunigen, usw.
Motor_forward
For I = 10 To 255 Step 1
   Lcd_out
   Pwm_out = I
   If Program_mode <> 1 Then                       'Program beenden wenn Interrupt ausgelöst wurde
      Exit For
   End If
   Waitms 100
Next I
For I = 255 To 10 Step -1
   Lcd_out
   Pwm_out = I
   If Program_mode <> 1 Then
      Exit For
   End If
   Waitms 100
Next I
End Sub

'automatischer Programmablauf 2
Sub Prog2()                                                 'hohe Drehzahl, Pause, niedrige Drehzahl, Pause, usw...
Motor_break
Pwm_out = 0
Lcd_out
If Program_mode <> 2 Then                        'Program beenden wenn Interrupt ausgelöst wurde
   Exit Sub
End If
Wait 1
Motor_forward
Pwm_out = 255
Lcd_out
If Program_mode <> 2 Then
   Exit Sub
End If
Wait 3
Motor_break
Pwm_out = 0
Lcd_out
If Program_mode <> 2 Then
   Exit Sub
End If
Wait 1
Motor_forward
Pwm_out = 80
Lcd_out
If Program_mode <> 2 Then
   Exit Sub
End If
Wait 3
End Sub

'automatischer Programmablauf 3
Sub Prog3()                                           'Motor mit mittlerer Drehzahl vorwärts und rückwärts laufen lassen
Motor_backward
Pwm_out = 100
Lcd_out
If Program_mode <> 3 Then                   'Program beenden wenn Interrupt ausgelöst wurde
   Exit Sub
End If
Wait 3
Motor_break
Pwm_out = 0
Lcd_out
If Program_mode <> 3 Then
   Exit Sub
End If
Waitms 500
Motor_forward
Pwm_out = 100
Lcd_out
If Program_mode <> 3 Then
   Exit Sub
End If
Wait 3
Motor_break
Pwm_out = 0
Lcd_out
If Program_mode <> 3 Then
   Exit Sub
End If
Waitms 500
End Sub

Viel Spaß beim Nachbauen...

Keine Kommentare:

Kommentar veröffentlichen