Servo an Attiny85 über zwei Taster steuern und Rückmeldung mit LED

Hallo zusammen,

für ein analoges Modul meiner Modellbahn, würde ich gerne zur Weichenstellung Servos verwenden.

Mein Plan wäre, dafür einen Attiny85 zu verwenden.
Über einen Taster soll jeweils das hin- und herschalten ausgelöst werden.
Die jeweiligen Endlagen und die Geschwindigkeit soll über Potis einstellbar sein.
Außerdem soll die jeweilige Position über zwei LED's auf dem Stellpult angezeigt werden.

Leider bin ich programmiertechnisch noch nicht so weit, daß ich die Programmierung alleine hin bekomme.

Einen Sketch für die Hausbeleuchtung, den ich mit eurer Hilfe auf dem Arduino erstellt habe, habe ich auch schon mehrmals erfolgreich auf einen Attiny45 übertragen. Also das klappt schon mal.

Vermutlich gibt es ja schon irgendwo einen fertigen Sketch für meine Anwendung, nur habe ich bisher nirgendwo etwas gefunden.

Ich hoffe, daß ich von euch die selbe, super Unterstützung erhalte wie beim letzten mal!

Viele Grüße
Herbert

Ja, die Servolib funktioniert nicht im Attiny.

Aber du kannst ein Servo auch unkomliziert selbst ansteuern.

Ich habe ein Beispiel mit einer Funktion _Servo() mal angehängt, das basiert auf einer Idee von Jurs.
Mit der Variablen "pulseabstand" kann man auch etwas mit der Geschwindigkeit spielen.

Die Endlagen würde ich nicht über Poti einstellen, sondern Codieren.

Wenns denn unbedingt sein muß, kann kann das so gehen:

void loop(){
   int Winkel_1 = map(analogRead(A1), 0, 1023, 0, 90);
   int Winkel_2 = map(analogRead(A2), 0, 1023, 90, 160);
   int winkel;
   if (digitalRead(Taste1_Pin) == LOW) winkel = Winkel_1;
   if (digitalRead(Taste2_Pin) == LOW) winkel = Winkel_2;
  _Servo(winkel);
}

Das ist jetzt ganz quick and dirty. Ohne Entprellen, ohne Absicherung gegen doppelte Tastendrücke etc.
Sollte aber grob fuktionieren.

Servo_Funktion.ino (2.09 KB)

1 Like

Moin Herbert,

wir hatten ja schon (vor langer Zeit) einmal das Vergnügen per EMail wg. des "belebten Hauses".
Mit Servos am ATtiny45 auf der Moba habe ich schon einiges gemacht. Anbei ein Sketch, der die "SoftwareServo"-Lib verwendet, da - wie Gunter schon angemerkt hatte - die normale ServoLib mit dem ATtiny nicht funktioniert.
Mit diesem Sketch können zwei Servos betrieben werden. Für jeden Servo werden folgende Parameter im Code abgelegt:
Min-Winkel
Max-Winkel
Verstellgeschwindigkeit in Richtung AUF
Verstellgeschwindigkeit in Richtung AB
Überschwingwinkel AUF (ein mal)
Überschwingwinkel AB (ein mal)

Damit kann man z.B. Signale, Schranken oder sonst was betreiben.

Probier dies erstmal aus...

[Wenn Du damit weiter kommst und dann immer noch mehr willst: ich habe auch mal mit 3 ATtiny45 die Tore eines 5-ständigen Lokschuppens gesteuert]

ServoControlATT45_V02_00.ino (7.46 KB)

Hallo zusammen,

danke erst mal für die Tipps!

Ich habe mal einen Schaltplan gezeichnet wie ich mir das vorstelle.
Da ich nicht der große Elektroniker bin, würde ich euch bitten mal darüber zu schauen ob ich gravierende Fehler darin habe.

Auf die Geschwindigkeitsregelung habe ich verzichtet. Die Endlageneinstellung über Potis ist mir jedoch wichtig.

Viele Grüße und einen schönen Restsonntag
Herbert

herbi39:
Auf die Geschwindigkeitsregelung habe ich verzichtet. Die Endlageneinstellung über Potis ist mir jedoch wichtig.

Bei Deinen LEDs kann ich nicht erkennen, wie das funktionieren soll. Da es sich wohl um 20mA Signal-LEDs handelt, würde ich einfach jede LED mit Vorwiderstand an einen Controller-Pin hängen.

Warum hast Du die Vorwiderstände R1 und R7 vor den Potis?
Wenn diese Vorwiderstände fehlen, kannst Du an den ADC-Pins den vollen Messbereich von 0 bis 1023 ausschöpfen und es ist Sache der Software, auf welchen Drehwinkel der Servo bei welchem ADC-Messwert gestellt wird.

Hast Du auch schon mal daran gedacht, dass man mit einem einzigen Taster ggf. mehrere verschiedene Funktionen steuern kann? Und dass Du ggf. mit nur einem einzigen Poti die Einstellung für

  • Endlage links
  • Endlage rechts
  • Geschwindigkeit
    erledigen könntest?

Beispielhaft:
Am Taster werden "kurzer Tastendruck" und "extrem langer Tastendruck" ausgewertet. Sagen wir mal wie folgt:

  • kurzer Tastendruck unter 3 Sekunden ==> Weiche umstellen
  • superlanger Tastendruck über 3 Sekunden ==> Wechseln in den "Programmiermodus".

Die Stellung des Potis wird dabei nur im Programmiermodus ausgewertet und der Programmiermodus wird an den LEDs signalisiert, z.B. mit Blinkzeichen. Bestätigung einer Einstellung mit einem kurzen Tastendruck.

Etwa wie folgt:

  • langer Tastendruck ==> Programmiermodus, rote LED blinkt, linke Endlage mit Poti einstellen
  • Doppelklick ==> grüne LED blinkt, rechte Endlage mit Poti einstellen
  • Doppelklick ==> beide LEDs blinken, Stellgeschwindigkeit kann eingestellt werden
  • Doppelklick ==> Einstellwerte im EEPROM speichern, zurück zum Normalbetrieb
    Oder wahlweise im Programmiermodus:
  • Einfachklick ==> Abbruch des Programmiermodus ohne zu speichern

Du müßtest dann natürlich eine Tasterabfrage haben, die zwischen Einfachklick, Doppelklick und Superlangdrücken des Tasters unterscheiden kann. Aber das wäre rein eine Sache der Software.

So wie Deine Schaltung aussieht, möchtest Du wohl gar nicht zwischen "Normalbetrieb" und "Programmiermodus" unterscheiden, so dass ggf. jedes versehentliche Verstellen der Potis zu anderen Endlagen an der Weiche führt. Mit dem skizzierten "Programmiermodus" würdest Du die Endlagen und die Stellgeschwindigkeit aber quasi einmal einstellen und speichern, und danach kannst Du die Potistellung vergessen und bist nur noch im Normalbetrieb: Klick am Taster und die Weiche schaltet um.

Hallo jurs,

vielen Dank für deine ausführliche Antwort.

Die Widerstände an den Potis habe ich mir in einem anderen Schaltplan abgeschaut, wenn diese jedoch den Regelbereich einschränken, werde ich sie natürlich wieder entfernen.

Das mit den verschiedenen Modi über einen Taster wäre zwar schön, aber nicht unbedingt nötig, da die Geschwindigkeit garnicht und die Endlagen nur dann nachgestellt werden müßen, wenn sich eventuel mal etwas durch Temperaturschwankungen verändert haben sollte.
Außerdem fühle ich mich ja schon mit einem einfachern Sketch für den Attiny überfordert und suche deshalb hier Hilfe.

Funktioniert das mit den LED's so nicht? Denn ich habe ja keinen freien Controllerpin mehr.

Viele Grüße
Herbert

Du kannst schon Zwei LEDs mit einem Pin steuern:

Aber ich gebe Jurs recht:
Du willst ja wahrscheinlich mehr als nur eine Weiche steuern. Da würde sich der Aufwand, die Endlagen über Tastendruck einstellen zu können, rentieren. Vor allem mußt du dann die Elektronik nicht mehr leicht zugänglich einbauen.

Noch was: Servos, vor allem billige, haben eine recht starke Temperaturdrift.
lege deinen mechanischen Antrieb so aus, dass er das kompensieren kann.
z.B. den Antrieb weich, federnd machen, so das man die Endstellung leicht überfahren kann.

2LED-1Pin.jpg

Hier wird noch ein Widerstand empfohlen wenn man beide LEDs komplett abschalten möchte:

herbi39:
Funktioniert das mit den LED's so nicht? Denn ich habe ja keinen freien Controllerpin mehr.

Wenn Du zwei LEDs mit einem Pin schalten möchtest, sollte das reichen:

                      ______
              +------|______|------>|--------0 -
              |         R1         rot        
              |        
Arduino 0-----+
              |         R2         grün              
              |       ______
              +------|______|-------|<-------0 +

Beide LEDs aus: INPUT
Rote LED ein: OUTPUT/HIGH
Grüne LED ein: OUTPUT/LOW

Beide LEDs ein bekommst Du dann nur über PWM.

Hallo zusammen,

ich habe jetzt mal den Plan angepasst

Ist das jetzt so wie ihr das gemeint habt?

Gibt es vielleicht irgendwo einen Sketch der ähnlich dem erforderlichen ist, den ich vielleicht nur ein bißchen ändern muß?

Nein, ich frage nicht weil ich zu faul bin micht selbst hin zu setzen und zu programmieren, sondern weil meine Ahnung einfach noch nicht ausreicht um das alleine umzusetzen.

Ich habe festgestellt, daß ich am einfachsten lerne, wenn ich mit gut dokumentierten Sketches experimentiere.

Vielen Dank und Grüße
Herbert

LED2 ist falschrum.

Üblicherweise ist plus oben und Masse unten,
das erleichtert das lesen des Schaltplanes.

Und sketch hatte ich dir schon gepostet.

jurs:
Wenn Du zwei LEDs mit einem Pin schalten möchtest, sollte das reichen:

                      ______

+------||------>|--------0 -
             |         R1         rot        
             |        
Arduino 0-----+
             |         R2         grün              
             |       ______
             +------|
|-------|<-------0 +




Beide LEDs aus: INPUT
Rote LED ein: OUTPUT/HIGH
Grüne LED ein: OUTPUT/LOW

Beide LEDs ein bekommst Du dann nur über PWM.

Da im Falle daß der Arduino-Pin als Input geschaltet ist (hochohmig) fließt ein kleiner Strom über die beiden Vorwiderstände und die beden LED und läßt die beiden LED leicht leuchten.

Grüße Uwe

fließt ein kleiner Strom über die beiden Vorwiderstände und die beden LED und läßt die beiden LED leicht leuchten.

Ja, wird aber besser, wenn man jeweils 2 Led hintereinander hängt oder mit weissen LED (3V). Da reichen die 5V nicht mehr für alle LED. Widerstände muss man natürlich anpassen.

Da es hier aber um eine Ansteuerung für eine Weiche geht, nehme ich mal an, dass immer eine der beiden LEDs leuchtet.
Für den Fall, dass der Zustand "beide aus" auch erwünscht ist, müsste man, abhängig von der Durchlassspannung der Dioden, noch Dioden mit reinhängen. Aber das dürfte hier nicht nötig sein.

uwefed:
Da im Falle daß der Arduino-Pin als Input geschaltet ist (hochohmig) fließt ein kleiner Strom über die beiden Vorwiderstände und die beden LED und läßt die beiden LED leicht leuchten.

Nein, die LEDs glimmen nur wenn INPUT geschaltet ist und gleichzeitig der interne PullUp-Widerstand aktiviert ist. Strom an der roten LED dann ca. 60 bis 250 µA. Das kann man schon als Glimmen erkennen. Dazu zwingt einen diese Schaltung aber nicht.

Die LEDs glimmen überhaupt nicht, wenn INPUT geschaltet ist und der interne PullUp-Widerstand abgeschaltet wird. Strom dann unter 1 µA und damit nicht mehr als Glimmen erkennbar.

@herbi39:
Reicht Dir das gepostete Beispiel zur Servoansteuerung ohne Library oder brauchst Du noch ein Sketch-Beispiel, das alle Hardware (Button, LEDs, Servo) im Zusammenspiel ansteuert?

Hallo Jurs,

wenn du mir noch einen zum jetzigen Schaltplan passenden Sketch schreiben könntest, wäre das super.

Ich möchte das ganze, wenn es mal funktioniert, dann auch als Bastelprojekt auf meiner Homepage (absolut unkommerziell) veröffentlichen, wie ich es auch schon mit dem belebten Haus gemacht habe.

Ich hoffe daß das für dich o.k. ist.

Bei der Hausbeleuchtung wurde mir von dir ja auch viel geholfen.

Von den inzwischen über 68000 Besuchern, waren ca.30% nur wegen dem Haus auf meiner Seite.

Aufgrund des Feedbacks in den Modellbahnforen und auch per Mail, sehe ich, daß es für viele Modellbahner, die vorher nichts von Programmierung wissen wollten, der Auslöser war sich ein Arduino zu kaufen und sich damit auseinander zu setzen.

Viele Grüße
Herbert
www-herberts-n-projekt.de

OT, denn -- wie guntherb schon festgestellt hat -- wird das hier gar nicht gebraucht.

jurs:
Nein, die LEDs glimmen nur wenn INPUT geschaltet ist und gleichzeitig der interne PullUp-Widerstand aktiviert ist. Strom an der roten LED dann ca. 60 bis 250 µA.

Bei mir leuchten eine Rote und eine Grüne LED, wenn man sie hintereinander an 5 V und zwei Widerständen anschliesst.

5V ------>|--- R1 ---+--- R2 --->|-----GND
                     |
Input Pin -----------+

Ob in der Mitte ein Arduino Pin auf INPUT sitzt oder nichts, macht da keinen merklichen Unterschied.
Auch INPUT_PULLUP ist noch recht hochohmig, so dass das keinen großen Unterschied macht.

Bei 2* 220 Ohm ergibt sich ein Strom von ca. 2 mA, der bei üblichen LEDs mehr als ein Glimmen verursacht.

herbi39:
wenn du mir noch einen zum jetzigen Schaltplan passenden Sketch schreiben könntest, wäre das super.

OK, anbei mal ein erster Versuch.
Ungetestet, können also Fehler drin sein.

// Model railway switch (untested) by 'jurs'

// use button with INPUT and external pull-down resistor 
// or with INPUT_PULLUP and internal pull-up resistor
#define BUTTONPIN 2
#define INPUTMODE INPUT  // INPUT or INPUT_PULLUP
#define LEDPIN 3
#define POTILEFT 4
#define POTIRIGHT 5
#define SERVOPIN 6
#define SERVOMIDDLE 1500 // 1500µs impulse duration means servo middle position

// define some symbolic constants
enum {LEFT, RIGHT};     // directions
enum {OFF, RED, GREEN}; // LED states

int currentOrientation; 

void switchLED(int ledState)
{
  switch(ledState)
  {
    case RED: 
      pinMode(LEDPIN,OUTPUT);
      digitalWrite(LEDPIN,HIGH);
      break;
    case GREEN:
      pinMode(LEDPIN,OUTPUT);
      digitalWrite(LEDPIN,LOW);
      break;
    default: 
      pinMode(LEDPIN,INPUT);
      digitalWrite(LEDPIN,LOW);
  }
}

void switchServo(int orientation)
{
  switchLED(OFF);
  unsigned long time=millis();
  while (millis()-time<500) updateServo(orientation); // half second delay updating the servo
  if (orientation==LEFT) switchLED(RED);
  else switchLED(GREEN);
  currentOrientation=orientation;
}

void updateServo(int orientation)
{
  int servoImpulse=SERVOMIDDLE;
  if (orientation==LEFT) servoImpulse-= analogRead(POTILEFT)/3;
  else servoImpulse+= analogRead(POTIRIGHT)/3;
  digitalWrite(SERVOPIN,HIGH);
  delayMicroseconds(servoImpulse);
  digitalWrite(SERVOPIN,LOW);
  delayMicroseconds(20000-servoImpulse);
}

boolean buttonPressed()
{
  boolean result=false;
  static byte lastButtonState;
  byte buttonState = digitalRead(BUTTONPIN);
  if (INPUTMODE==INPUT_PULLUP) buttonState=!buttonState;
  if (buttonState == HIGH && lastButtonState == LOW) result=true;
  lastButtonState=buttonState;
  return result;
}


void setup() {
  pinMode(BUTTONPIN, INPUTMODE);
  pinMode(LEDPIN, OUTPUT);
  pinMode(SERVOPIN, OUTPUT);
  switchServo(LEFT);
}

void loop() {
  if (buttonPressed())
  {
    if (currentOrientation==LEFT) switchServo(RIGHT);
    else switchServo(LEFT);
  }    
  updateServo(currentOrientation);
}

In Deiner Schaltung hast Du einen externen PullDown-Widerstand am Button, also "INPUTMODE INPUT". Dasselbe Programm könnte auch mit den internen PullUp-Widerstand aktivieren und mit INPUT_PULLUP betrieben werden, aber das ist nur sinnvoll, wenn sich der Button sehr nahe am Controller befindet und mit einer kurzen Leitung angeschlossen ist.

Der beabsichtigte Ablauf ist wie folgt:
Beim Einschalten fährt der Servo in eine Richtung.
Während der Servofahrt werden die LEDs für eine halbe Sekunde ausgeschaltet.
Nach der Servofahrt wird die eine oder die andere LED eingeschaltet.
Mit den Potis kann die Servo-Sollposition eingestellt werden, und zwar ausgehend von der Servo-Mittellage.

Die eine Sollposition ergibt sich aus der Mittellage bei 1500µs Impulsdauer + ADC-Messwert/3, beim anderen Sollwert wird ADC-Messwert/3 abgezogen.

Da der ADC-Messwert bis zu 1023 betragen kann, variiert die Servo-Impulsdauer also
1500 +/-341
Da eine Impulsveränderung von 500µs typischerweise einem Drehwinkel von 90° entsprechen, kann mit den Potis jeder Endanschlag um ca. 60° verändert werden.
Also Linkswert 90° ... 30° Servowinkel einstellbar und Rechtswert 90° ... 150° Servowinkel einstellbar.
Bei Servomittelstellung beider Potis sollte der Servo also zwischen ca. 60° und 120° Stellwinkel drehen.

Die Drehgeschwindigkeit des Servos wird bei diesem Programm nicht künstlich ausgebremst, sondern der Servo läuft quasi mit der ihm eigenen maximalen Stellgeschwindigkeit zwischen den Endpositionen.

Probier's mal aus, ob das so grob funktioniert!
Wenn nicht, müßte ich mir selbst mal einen kleinen Versuchsaufbau mit LEDs, Potis und Servo machen.

michael_x:
Bei 2* 220 Ohm ergibt sich ein Strom von ca. 2 mA, der bei üblichen LEDs mehr als ein Glimmen verursacht.

Stimmt, Du hast Recht! Mit INPUT sind nicht beide LEDs aus, sondern tatsächlich beide LEDs an.

Da müßte sich der OP mal äußern, ob er mehr als zwei LED-Signale überhaupt braucht.

jurs:
Die Drehgeschwindigkeit des Servos wird bei diesem Programm nicht künstlich ausgebremst, sondern der Servo läuft quasi mit der ihm eigenen maximalen Stellgeschwindigkeit zwischen den Endpositionen.

Die meisten Servos kann man leicht ausbremsen, in dem man die Pulse nicht alle 20ms, sondern seltener sendet.
Ich habe es mal bis zu einem Puls pro sekunde getest (bei einem billig Servo), was dazu führt, dass das Servo alle 1sek einen kurzen Zucker in Richtung Ziel macht.

Ansonsten muß ich dir einfach mal gratulieren, Jurs, du schreibst einen sehr eleganten Code!