Servoarm auf Zeitskala (mit Arm Sekunden anzeigen)

Hallo zusammen,

ich versuche derzeit eine möglichst genaue (auf die Sekunde genau :slight_smile: )
Anzeige mittels eines Servos zu realisieren.
Der Servo Arm soll sich auf einer 100° großen Skala bewegen und dabei die
Sekunden von 0-100 anzeigen.

Hat da schon jemand Erfahrung sammeln können, ob die China Modellbau Servos
dafür genügen?

ver. Varianten für den Servo

	//0.70588°/PWM_x (bei 180° Servo)
	//141.6667PWM_x/° (bei max 100°, 0.70588*141,6667=~100)
	//servo_pos = zaehler_dec * 2.575;
	//servo_pos = zaehler_dec + 55;
	servo_pos = map(zaehler_dec, 0, 99, 0, 255);
	analogWrite(AQ_Pin, servo_pos);

UPDATEvollständiger Code (soll eine Eieruhr werden)

//BCD_7SEG Zaehler v1.4B            (Max B. 05.10.2017)
//Zaehler +/-/reset, Ausgabe auf BCD 7-Segment 2 Digits
//min.=0; max.=99; load=60;
//wenn +/- >=1s = +/- 1Hz Takt
//////////////////////////////////////////////////////////
// UMBAU auf Sekunden mit Servo und minuten mit 2x7-SEG //
// ab 60 Sekunden Minuten += 1; bei minus -= 1;         //
//                                                      //
//////////////////////////////////////////////////////////
//(UnoArduSim) #include <pgmspace.h>

//Ein-/Ausgaenge
//Analog-Eingaenge da IO-Mangel
const uint8_t S0_CU = A0; bool plus = 0;
const uint8_t S1_CD = A1; bool minus = 0;
const uint8_t S2_CR = A2; bool reset = 0;
const uint8_t S3_CL = A3; bool zload = 0;
//------------BCD_Einer------------------BCD_Zehner----
const uint8_t BCD_1_1 = 2; const uint8_t BCD_1_10 = 6;
const uint8_t BCD_2_1 = 3; const uint8_t BCD_2_10 = 7;
const uint8_t BCD_4_1 = 4; const uint8_t BCD_4_10 = 8;
const uint8_t BCD_8_1 = 5; const uint8_t BCD_8_10 = 9;
const uint8_t servo = 10;
const uint8_t alarm = 13;
//Variablen
bool s_x = 0;                  //Merker fuer letzte Eingabe
bool m_reset = 0;              //Merker fuer Reset
byte zaehler_dec = 0;          //DEC Zaehler 0-100
word zaehler_bcd = 0;          //BCD Zaehler 0-160
const uint8_t zaehler_ld = 60; //Zaehlerstand laden
const uint16_t m_1s = 1000;    //1 Sekunde
unsigned long j_ms = 0;        //Zeitpunkt "jetzt"
unsigned long l_ms = 0;        //Zeitpunkt "zuletzt"
unsigned long alarm_ms = 0;    //Zeitpunkt "alarm"
uint8_t servo_pwm = 0;        //Servo Position


void setup() //(OB100)
{//Start setup
	Serial.begin(19200);
	pinMode(S0_CU, INPUT);    pinMode(S1_CD, INPUT);
	pinMode(S2_CR, INPUT);    pinMode(S3_CL, INPUT);
	pinMode(BCD_1_1, OUTPUT); pinMode(BCD_1_10, OUTPUT);
	pinMode(BCD_2_1, OUTPUT); pinMode(BCD_2_10, OUTPUT);
	pinMode(BCD_4_1, OUTPUT); pinMode(BCD_4_10, OUTPUT);
	pinMode(BCD_8_1, OUTPUT); pinMode(BCD_8_10, OUTPUT);
	pinMode(servo, OUTPUT);
	pinMode(alarm, OUTPUT);
	
	while (!Serial) {/*NICHTS*/} //auf serielle Uebertragung warten
	Serial.println(F("\nEingabe Pin: A0=plus, A1=minus, A2=reset, A3=zload"));
	Serial.println(F("Ausgabe Pin: BCD_1=2-5, BCD_10=6-9"));
	digitalWrite(alarm, HIGH);
	Servo_test();
	digitalWrite(alarm, LOW);
	Serial.println(F("\nBetriebsbereit..."));
	DEC_zu_BCD();
}//Ende setup


void loop() //(OB1)
{//Start loop
	//Eingaenge einlesen (erspart Platz)
	plus  = digitalRead(S0_CU);
	minus = digitalRead(S1_CD);
	reset = digitalRead(S2_CR);
	zload = digitalRead(S3_CL);
	
	j_ms = millis();
	
	//Freigabe fuer weitere Eingabe, sobald keine Taste gedrueckt ist.
	if (plus + minus + reset == 0) 
	{
		s_x = 0;
		l_ms = millis(); //1Hz zaehler blockieren
	}
	//Taster reset
	if (reset == 1 && (s_x + m_reset == 0))
	{
		Serial.println(F("\nReset..."));
		zaehler_dec = 0;
		zaehler_bcd = 0;
		s_x = 1;
		m_reset = 1;
		Bit_lesen();
		Servo_akt();
		return;
	}
	//Taster zload
	if (zload == 1 && (plus + minus + reset + s_x == 0) && zaehler_dec != 60)
	{
		zaehler_dec = 60;
		s_x = 1;
		m_reset = 0;
		DEC_zu_BCD();
		Bit_lesen();
		Servo_akt();
		return;
	}
	//Taster plus
	if (plus == 1 && (minus + zload + reset + s_x == 0) && zaehler_dec < 99)
	{
		zaehler_dec += 1;
		s_x = 1;
		m_reset = 0;
		DEC_zu_BCD();
		Bit_lesen();
		Servo_akt();
	}
	//Taster minus
	if (minus == 1 && (plus + zload + reset + s_x == 0) && zaehler_dec > 0)
	{
		zaehler_dec -= 1;
		s_x = 1;
		m_reset = 0;
		DEC_zu_BCD();
		Bit_lesen();
		Servo_akt();
	}
	//zaehlen mit 1Hz
	if ((j_ms - l_ms >= m_1s) && ((plus == 1 && zaehler_dec < 99) || (minus == 1 && zaehler_dec > 0)))
	{
		s_x = 0; //weiteres zaehlen freigeben
		l_ms = millis();
	}
	//Alarm ab 99 oder ab 0 wenn minus aktiv
	if ((zaehler_dec >= 99 || (zaehler_dec < 1 && minus == 1)) && (j_ms - alarm_ms >= m_1s))
	{
		digitalWrite(alarm, digitalRead(alarm) ^ 1);
		alarm_ms = millis();
	}
	else if ((zaehler_dec < 99 && minus == 0) || (zaehler_dec > 0 && minus == 1))
	{
		digitalWrite(alarm, LOW);
	}
}//Ende loop

void DEC_zu_BCD() //(FC1)
{
	//|-BCD-----=--------DEC-------HEX----+-------MOD(10)-|
	zaehler_bcd = (zaehler_dec / 10 * 16) + (zaehler_dec % 10);
	Serial.print(F("Zaehlerstand = "));
	Serial.print(zaehler_dec);
	Serial.print(F(" | BCD = "));
	Serial.println(zaehler_bcd, BIN);
}

void Bit_lesen() //(FC2)
{
	//erste 4Bit "Einer"
	digitalWrite(BCD_1_1, bitRead(zaehler_bcd, 0));
	digitalWrite(BCD_2_1, bitRead(zaehler_bcd, 1));
	digitalWrite(BCD_4_1, bitRead(zaehler_bcd, 2));
	digitalWrite(BCD_8_1, bitRead(zaehler_bcd, 3));
	//letzte 4Bit "Zehner"
	digitalWrite(BCD_1_10, bitRead(zaehler_bcd, 4));
	digitalWrite(BCD_2_10, bitRead(zaehler_bcd, 5));
	digitalWrite(BCD_4_10, bitRead(zaehler_bcd, 6));
	digitalWrite(BCD_8_10, bitRead(zaehler_bcd, 7));
}

void Servo_test() //(FC3)
{
	Serial.print(F("Servo wird geprueft..."));
	uint8_t x = 188;
	for (x; x > 0; x--)
	{
		analogWrite(servo, x);
		delay(10);
	}
	for (x; x < 188; x++) 
	{
		analogWrite(servo, x);
		delay(10);
	}
	Serial.println(F("fertig"));
}

void Servo_akt() //(FC4)
{
	servo_pwm = map(zaehler_dec, 0, 60, 188, 1);
//absichern des servos, da ab +60 wert ~255;
//wird ueberfluessig durch begrenzung des zaehlers auf sekunde
	servo_pwm = constrain(servo_pwm, 1, 188);
	analogWrite(servo, servo_pwm);
}

Nein, die reichen eher nicht. Ausnahmen werden die Regel bestätigen. Nimm einen Schrittmotor mit Getriebe und Endanschlag zum kalibrieren.

Wobei für ne Eieruhr könnte es gerade noch gehen

Sehe ich auch so - kommt ja nicht so genau auf die Sekunde an beim rumeiern :smiling_imp:

Wobei 100 Sekunden für eine Eieruhr auch eher untypisch sind. Ich koche Eier immer im höheren einstelligen Minutenbereich.

Danke Euch!

Hatte mir gedacht es sähe nicht schlecht aus mit einem analogen Sekunden Zeiger

es gibt ja noch die 2 7-SEG Anzeigen, welche ja noch für die Minuten umfunktioniert werden können :)

Klaus_ww: Wobei 100 Sekunden für eine Eieruhr auch eher untypisch sind. Ich koche Eier immer im höheren einstelligen Minutenbereich.

Uhr-Zeiger laufen normalerweise im Kreis und sind daher weniger für Servos als für Stepper geeignet. Aber früher gab es auch mal sowas: Da kommst du mit den Bewegungsmöglichkeiten eines Servos (100° ... 180°) etwa hin.

michael_x: Uhr-Zeiger laufen normalerweise im Kreis und sind daher weniger für Servos als für Stepper geeignet. Aber früher gab es auch mal sowas: Da kommst du mit den Bewegungsmöglichkeiten eines Servos (100° ... 180°) etwa hin.

Das Ticken ist aber schwer mit einem Servo zu simulieren ;) ;)

Das Ticken ist aber schwer mit einem Servo zu simulieren

Dafür hat ein Uno 20 Signal-Pins. Kannst ja mehr als einen Servo anschliessen.

Keine Led leuchten lassen, und das solide Gehäuse, wären für mich die schwierigsten Herausforderungen. ;)

uwefed: Das Ticken ist aber schwer mit einem Servo zu simulieren ;) ;)

Ticken würde ich natürlich mit einem mp3-Player machen, dann ist zwischen Kirchturmuhr-Ticken und Armbanduhr alles möglich :)

Wo bekommst Du denn das Ticken vom Steffl her? ;) ;) ;)

Ihr bringt mich auf gute Ideen für das Design. :)

michael_x: Uhr-Zeiger laufen normalerweise im Kreis und sind daher weniger für Servos als für Stepper geeignet.

Das wird nicht weiter schlimm sein, dann wird der Zeiger eben von 60 wieder nach links auf 0 (oder die Stelle, welche er bis dahin darstellen soll) laufen.

Ich habe mal den Code im ersten Post aktualisiert und werde Euch berichten, sobald ich wieder Zeit für das mini Projekt gefunden habe.

Bis dahin noch eine schöne Woche! :)

Ich habe gerade mal einen kleinen Test gemacht, was die Auflösung des Servos betrifft.

Ansteuerung über Servo lib in uS, von 1000 bis 2000, Servi Corona Ds-939MG, also nicht das billigste, 3€ glaub ich.
Ich habe einen ca. 15cm langen Zeiger drangemacht

/* Sweep
 by BARRAGAN <http://barraganstudio.com>
 This example code is in the public domain.

 modified 8 Nov 2013
 by Scott Fitzgerald
 http://www.arduino.cc/en/Tutorial/Sweep
*/

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0;    // variable to store the servo position

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
  Serial.begin(115200);
}

void loop() {
  for (pos = 1000; pos <= 2000; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    Serial.println(pos);
    delay(50);                       // waits 15ms for the servo to reach the position
  }
  for (pos = 2000; pos >= 1000; pos -= 3) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    Serial.println(pos);
    delay(150);                       // waits 15ms for the servo to reach the position
  }
}

Es macht nur ca. 123 Ruckler, und die Ruckler vorwärts und Rückwärts gleich.

Bei einem Futaba 9250 sieht das ganze schon wesentlich smoother aus, und man merkt den Unterschied, ob ich mit1 oder 3 uS inkrementiere.

uwefed: Wo bekommst Du denn das Ticken vom Steffl her? ;) ;) ;)

Da tickt leider schon lange nichts mehr :) Die Uhren vom Stephansdom sind sehr modern und schon ziemlich lange elektrisch angetrieben (ich glaub seit den 1930ern). Übrigens hat der Stephansdom schon seit 1862 eine "Digitaluhr", mit Zahlenanzeige (siehe: Die Uhren von Sankt Stephan )

Die Uhrzeiger kann man ja auch ziemlich lange machen :) |500x375