Außenbordmotor Gas-Steuerung

Bauteile:

  • Aluminiumblech
  • div. Kleinteile (Schrauben, Muttern)
  • Modellbau-Servo
  • Attiny13 Microcontroller
  • div. Elektronik-Komponenten (IC-Sockel, LED´s, Poti, Schalter, Widerstände, Dioden, Spannungsregler, Kondensatoren…)

Aufbau:

An das Gehäuse des Motors habe ich ein starkes Aluminiumblech geschraubt, welches eine Aussparung für das Servo hat.
Das Servo wurde leicht modifiziert (Plastikhebel gepimpt durch Aluhebel um längeren Hebel und stabileren Aufbau zu erhalten)
und über Alu-Teile mit dem vorhandenen Hebel des Gas-Zugs verbunden.

Die Steuereinheit des Servos habe ich auf der anderen Seite des Motors untergebracht udn zwecks besserer Kühlung ( der Spannungsregler heizt ganz schön )
an ein Alublech und dieses mit dem Motor verschraubt. ( Kühlung am Motorblock klingt ein wenig komisch, da der Motor ja selbst heiß wird, aber die Maximaltemperatur des
Motors sollte noch locker in den Grenzen der Elektronik liegen … )

Über ein externes Steuerpanel welches über ein Netzwerkkabel (8 Pole + Masse) mit der Steuereinheit verbunden ist kann nun das Servo gesteuert, die Vollgas und Leerlaufstellung eingestellt, über zwei LED´s die Betriebszustände abgelesen sowie das ganze System abgeschaltet werden.

Bilder:

Aluschiene mit Servo-Halterung

Steuereinheit

Steuerpanel

 

Elektrischer Aufbau:

Als Betriebsspannung wird die 12 VDC Bordspannung vom Boot, bzw. in Zukunft evtl. direkt die 12 VDC Generatorspannung des Motors verwendet. (Die Schaltung muss ja auch nur laufen wenn der Motor läuft)
Da die Spannung für den Attiny13 zu hoch ist wird diese mittels Linearspannungsregler 78S05 auf 5 Volt geregelt. Die restliche Schaltung sowie das Servo wird mit diesen 5V versorgt wobei beim Spannungsregler durch
die Spannungsdifferenz von 7V und die Stromaufnahme des Servos im Betrieb relativ viel Wärme entsteht. Diese leite ich mittels Alublech welches mit dem Motorblock verschraubt ist ab. Theoretisch sollte die maximale
Temperatur die der wassergekühlte Motorblock erreicht immer noch einiges unter der Maximaltemperatur des Spannungsreglers liegen und dieser das Ganze somit überleben.. Theoretisch :)… die Praxis wirds zeigen aber
zur Not hat der Spannungsregler ja selbst noch eine Übertemperatursicherung eingebaut. Zusätzlich habe ich ja im Programm eine Routine eingebaut welche den Servo abstellt sofern keine Änderung an der Servostellung
übermittelt wird. Das spart einiges an Stromaufnahme gegenüber der vorherigen Lösung wo das Servo quasi permanent geregelt hat.

Die Steuerspannung von ca. 0-5 VDC kommt von einem Poti an einem Spannungsteiler und wird vom Attiny13 in entsprechende PWM-Signale umgesetzt.

 

Programmierung des Attiny13:

Der Attiny13 ist für diese Aufgabe gerade noch verwendbar da der Programmspeicher von 1000 Bytes sehr sehr schnell voll ist.
Mein C-Programm hat aktuell irgendwas um die 988 Bytes und folgende Features:

  • Auslesen einer Spannung zw. 0 und 5V (Steuerspannung vom Poti)
  • PWM-Ausgabe (Servo-Steuerimpuls)
  • Unterbrechen der PWM-Ausgabe solange keine Änderung der Steuerspannung erfolgt. ( Bringt Entlastung für den Spannungsregler )
  • Trotz Unterbrechung alle paar Sekunden einen Steuerimpuls schicken um eventuelle Servoverstellungen(durch Vibrationen oder manuelle Verstellung des Gasgriffs) zu korrigieren.
  • Digital Ausgang für Status-LED ( Steuerung ein oder aus, Anzeigen der Einstellmodi )
  • Anzeige ob das Servo Steuerimpulse erhält ( wird einfach mittels LED am PWM-Pin realisiert )
  • Auslesen von zwei Digitaleingängen ( Einstellmodi werden hierüber festgelegt )
  • Speicherung der Einstellungen im EEPROM damit der Servoweg nicht jedes Mal neu eingestellt werden muss.

Profis werden sich vermutlich krumm lachen über meinen Code aber hey.. er funktioniert 😉 Während der Programmierung haben sich auch noch so einige Lerneffekte eingestellt
z.B. dass die delay.h, die ich hier nicht verwende, nur in den Attiny passt wenn konstante Werte übergeben werden. (Diese Erkenntnis kam zu spät, deshalb habe ich meine eigenen
Warteroutinen zusammengebastelt)

Hier nun also der Code:

/*
 * Atiny13_Servoctrl.c
 *
 * Created: 04.05.2011 20:51:06
 *  Author: Stefan
 *
 * Servo Steuerung
 * PB0 PWM OUT
 * PB1 CONTROL LED
 * PB2 if low, set lower limit
 * PB3 if low, set upper limit
 * PB4 ADC input 0-5V full right to full left
 * PB5 RESET
 * VCC
 * GND
 */

#include <avr/io.h>
#include <avr/eeprom.h>

int limit_l;
int limit_h;
int lastval;
unsigned char sdc;
unsigned char pwmoff;

void init(){
  //PORT init-------------------------------------------
  //configure PORTB0 as Output
  DDRB = (1<<PB0) | (1<<PB1);
  PORTB = (1<<PB3) | (1<<PB2) | (1<<PB1);
  //ADC init--------------------------------------------
  // 10-Bit Mode, single shot mode, channel PB4
 // ADMUX = (1<<ADLAR) | (1<<MUX1);
  //prescaler 8, enable ADC, freerunning
  //evtl channel einzeln PB4,10 PB5,00 PB2,01 PB3,11 (MUX1,MUX0)
//  ADCSRA = (1<<ADPS0) | (1<<ADPS1) | (1<<ADEN) |(1<<ADSC)| (1<<ADATE);
  //start Timer-----------------------------------------
  OCR0A = 200;
  TCCR0A = (1<<COM0A1) | (1<<COM0A0) | (1<<WGM02) | (1<<WGM00);
  //prescaler 64, Fast-PWM-Mode
  TCCR0B = (1<<CS01) | (1<<CS00); //(1<<CS01) | (1<<CS00); //(1<<CS02);
  //
  limit_l = eeprom_read_byte(0);
  limit_h = eeprom_read_byte(1);
  //limit_h = 255;
  //limit_l = 0;
  sdc = 0;
  lastval = 0;
  pwmoff = 0;
}


int main(){
  init();
  while(1)
  {
		ADMUX = (1<<ADLAR) | (1<<MUX1);
        ADCSRA = (1<<ADPS0) | (1<<ADPS1) | (1<<ADEN) |(1<<ADSC);
        while(ADCSRA & (1<<ADSC));

        if( !(PINB & (1<<PINB2)) )
        {
			if( !(PINB & (1<<PINB3)) )
			{
				limit_l = 0;
				limit_h = 255;
				PORTB &= ~(1<<PB1);
				burntime(100,110);
				PORTB |= (1<<PB1);
				/*burntime(100,100);
				PORTB &= ~(1<<PB1);
				burntime(100,70);
				PORTB |= (1<<PB1);*/
			}
			else
			{
        		limit_l = ADCH;
				PORTB &= ~(1<<PB1);
				eeprom_write_byte(0,limit_l);
				burntime(100,50);
				PORTB |= (1<<PB1);
			}
        }
        else if( !(PINB & (1<<PINB3)) )
        {
        	limit_h = ADCH;
			PORTB &= ~(1<<PB1);
			eeprom_write_byte(1,limit_h);
			burntime(100,25);
			PORTB |= (1<<PB1); } else { //OCR0A = ADCH; OCR0A = maintain_limits(ADCH); } burntime(25,53); } return 0; } int maintain_limits( int val ) { if(val > limit_h)
		val = limit_h;
	if(val < limit_l)
		val = limit_l;
	if(val != lastval)
	{
		enable_pwm();
		sdc = 0;
	}
	else
	{
		if(pwmoff < 1) { sdc++; if(sdc > 3)
			{
			disable_pwm();
			pwmoff = 1;
			sdc = 0;	
			}
		}
		else
		{
			pwmoff++;
			if(pwmoff >= 254)
			{
				enable_pwm();
				pwmoff = 0;
			}
		}		
	}
	lastval = val;
	return val;
}

void burntime(int xct, int xct2)
{
	int ct;
	int ct2;
	ct = 0;
	ct2 = 0;
	while(ct2<xct)
	{
		ct = 0;
		while(ct<xct2)
		{
			ct++;
		}
		ct2++;
	}
}

void enable_pwm()
{
	TCCR0A = (1<<COM0A1) | (1<<COM0A0) | (1<<WGM02) | (1<<WGM00);
}

void disable_pwm()
{
	TCCR0A &= ~( (1<<COM0A1) | (1<<COM0A0) | (1<<WGM02) | (1<<WGM00) );
}

UPDATE: 25.07.2011, die eigene Steuerung für den Gas-Servo wurde abgebaut, die Funktionen werden von der BootSteuerung nun mitübernommen.

Details hierzu unter „Steuerung