LightBot – ATtiny Roboter


Warning: WP_Syntax::substituteToken(): Argument #1 ($match) must be passed by reference, value given in /home/www/nicomania_de/wp-content/plugins/wp-syntax/wp-syntax.php on line 380

LightBotAuch wenn man schon groß und erwachsen ist, so reizt es dann doch den Mann, mal ein kleines Spielzeug zu bauen, sei es auch noch so sinnfrei. Deshalb habe ich einen kleinen und einfachen Roboter bauen wollen, der dem Licht hinterher jagt. Dazu braucht es einen Mikrocontroller und zwei Lichtsensoren, damit die Richtung  des Lichts erkannt werden kann. Den Antrieb hatte ich ursprünglich mit zwei Vibrationsmotoren geplant, da mich diverse YouTube Videos inspiriert hatten, in denen ein „Brushbot“ mit einem Vibrationsmotor auf einem Zahnbürstenkopf durch die Gegend flitzt. Das Prinzip funktioniert recht gut, aber eine brauchbare Richtungssteuerung mit zwei Motoren links und rechts war nicht drin. Ich habe da viel experimentiert und Zeit verbraten, hohe und niedrige Spannung, Geschwindigkeit und verschiedene Montageorte. Vibrationsmotoren waren wohl für meinen Zweck nicht brauchbar. Deshalb bin ich zum altbewährten Fortbewegungsmittel zurückgekehrt: dem Rad. Schnell ein altes Spielzeugauto geschlachtet und auf die Wellen der Vibrationsmotoren geklebt. Damit war die Richtungssteuerung natürlich ein Traum! Schnell, effizient und präzise, auch wenns nicht ganz so lustig ist, wie ein vibrierend hüpfender Roboter 🙂

Die Hardware ist recht übersichtlich. Neben dem Mikrocontroller gibt es da einen Akku (Li-Po), zwei mini Elektromotoren, zwei LDR (lichtempfindliche Widerstände), zwei Transistoren, eine LED, ein Schalter und drei Widerstände. Das alles wollte ich auch so klein wie möglich unterbringen. Deshalb habe ich mir eine vollflächige Kupferplatine genommen und die Leiterbahnen frei mit einem Dremel ausgefräst. In meinem routing komme ich dabei mit einer Seite und zwei Durchkontaktierungen für die Motoren aus.

Lightbot_SchaltplanDer Mikrocontroller hat einen Spannungsbereich von 2,7 bis 5,5V, weshalb ich einen LiPo Akku aus dem Modellbau verwendet habe. Ich glaube, ich hatte ihn mal aus einem kleinen Helimodell ausgeschlachtet, der war so schön klein mit seinen 140mAh. Ein LiPo pendelt mit seiner Spannung zwischen 3,0 und 4,2V, deshalb brauchen wir keinerlei Spannungsregler und können direkt die Motoren und den Controller befeuern. Zum laden benutze ich entweder einen Modellbaulader oder einen USB Ladestecker. An der Unterseite habe ich dazu einen kleinen Stecker vorgesehen, denn der Akku ist festgeklebt und angelötet.

Der ATtiny kann pro Ausgangspin nur 20mA schalten, die Motoren ziehen pro Stück aber 50 bis 60mA, weshalb ich noch NPN Transistoren davor schalten musste. Ich habe die kleine BC849 Variante genommen, die gibt es als SMD Sot23 Baugröße. Wenn du alle Bauteile wie ich in SMD Größe benutzt, erfordert das Löten ein wenig Fingerspitzengefühl und eine Pinzette.

Als Lichtsensoren habe ich zwei LDRs verwendet. Das sind Lichtempfindliche Widerstände, die im Dunkeln ca. 500 kOhm und im Hellen ca. 0 Ohm haben. Zusammen mit einem einfachen Spannungsteiler mit zwei Festwiderständen von 10 kOhm ergibt das dann im Dunklen 0,5V und im Hellen 5V (VCC), die wir mit dem AD Wandler des ATtiny messen können (Ausgegangen von 5V Versorgungsspannung). Damit das Sichtfeld der einzelnen Sensoren nicht zu breit ist, habe ich ein Stück schwarzen Schrumpfschlauch darum geschrumpft. Wenn also der eine LDR eine höhere Helligkeit wahrnimmt, ist der zweite davon nicht beeinflusst und man kann einen eindeutigen Helligkeitsunterschied zwischen links und rechts feststellen.

Lightbot_Platine_anoAn einem Pin habe ich noch eine einzelne LED angeschlossen, damit ich diverse Statusmeldungen ausgeben kann. In meinem Code blinkt sie z.B. nach jedem Messdurchlauf drei Mal kurz hintereinander. Ich spiele aber schon mit dem Gedanken, diesen Pin einer IR Diode zu opfern, um evtl. die zweite Version des LightBot mit einer Infrarot-Fernbedienung zu steuern.

Hier findest du den Code für den ATtiny. Manches könnte man bestimmt anders lösen oder eleganter programmieren. Ich bin kein Informatiker und absolut offen für Vorschläge. Beispielsweise habe ich die Ansteuerung für die Motoren zwar mit PWM (Pulsweitenmodulation) erledigt, jedoch in Software. Man kann das auch in Hardware machen, da der ATtiny zwei Ausgänge dafür besitzt. Das hätte den Vorteil, dass er gleichzeitig die Helligkeit messen und sich bewegen kann. Ich habe den Code so gut es geht kommentiert, damit es nachvollziehbar bleibt. Dennoch setze ich ein gewisses Maß an Programmierkenntnisse in C voraus, denn ich kann hier leider keinen Programmierkurs abhalten. Die Bewegungen und Messungen habe ich in Funktionen ausgelagert, damit ich sie in der main nur kurz aufrufen muss, um mich rein auf die Steuerung konzentrieren zu können. Wenn du das Projekt nur nachbauen möchtest, findest du in der ZIP Datei auch die fertigen Hex Dateien zum direkten flashen für den ATtiny 13, 25 und 85. Diese Typen sind Pinkompatibel und reichen vom Speicherplatz aus.

Hier der Programmcode für den ATtiny:

[showhide more_text=“>> Hier klicken um Code anzuzeigen“ less_text=“<< Hier klicken um Code auszublenden“]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// Lightbot V1.1   ATtiny 13/25/85
 
// ************** Includes **************************************************
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 20000000UL	//Takt in Hz
 
// ************** Einstellungen *********************************************
#define toleranz   30	// Toleranz
 
#define tempoL     200	// PWM Tempo Motor links (0-255)
#define tempoR     200	// PWM Tempo Motor rechts (0-255)
#define tempoV     180	// PWM Tempo Motoren vor (0-255)
 
#define impulsL    18	// Impulsdauer Motor links (in ms)
#define impulsR    18	// Impulsdauer Motor rechts (in ms)
#define impulsV    15	// Impulsdauer Motoren vor (in ms)
 
#define ul         3	// U-Turn Impulse links
#define ur         4	// U-Turn Impulse rechts
#define i360       9	// Anzahl Schritte für u-turn
 
// ************** Variablen *************************************************
volatile int i,k,z;	// Zaehler und Zwischenspeicher
 
// ************** Function: Licht (0-1023) **********************************
int MESSWERT (int kanal){
 
  	int a=5, f=a, j=a;	// a>0 Anzahl der Messzyklen
	long int wert=0, wert1=0, wert2=0 ;
 
	ADCSRA=0x80; 		// ADC eingeschaltet, kein Prescale 
	ADMUX=kanal;		// Pin auswaehlen
	ADCSRA |=_BV(ADSC); 	// Dummymessung starten
	while (ADCSRA & (1<<ADSC)) {;}	// Dummymessung abwarten
 
	while(j){
 
		while(f){
			ADCSRA |=_BV(ADSC); 		// Messung starten
			while (ADCSRA & (1<<ADSC)) {;}	// auf Abschluss der Konvertierung warten 
			wert+=ADCW;			// Wert uebergeben
			f--;
		}
 
		wert1 = wert/a;		// Mittelwert bilden
		wert2 += wert1;
		j--;
	}
 
	wert=(wert2/a);
	return (wert);
}
 
int lichtL(void) 
{
	return (1023-MESSWERT(2));	// invertieren
}
 
int lichtR(void)
{
	return (1023-MESSWERT(3));	// invertieren
}
 
// ************** Function: Bewegung ****************************************
void vor(void) 
{
	k=255-tempoV;
	for(i=impulsV;i>0;i--)
	{
		PORTB |= 0b000011; 
		for (z=0; z<tempoV; z++);	
		PORTB &= 0b111100; 
		for (z=0; z<k; z++);
	}
	_delay_ms(100);
}
 
void links(void) 
{
	k=255-tempoL;
	for(i=impulsL;i>0;i--)
	{
		PORTB |= 0b000010; 
		for (z=0; z<tempoL; z++);	
		PORTB &= 0b111101; 
		for (z=0; z<k; z++);
	}
	_delay_ms(100);
}
 
void rechts(void) 
{
	k=255-tempoR;
	for(i=impulsR;i>0;i--)
	{
    		PORTB |= 0b000001; 
		for (z=0; z<tempoR; z++);	
		PORTB &= 0b111110; 
		for (z=0; z<k; z++);
	}
	_delay_ms(100);
}
 
void turn(void)
{
	if (lichtL()>lichtR())
		{
			for(int t = 0; t<=ul ; t++)
			{
				links();
				_delay_ms(10);
			}
		}
	else{
			for(int t = 0; t<=ur ; t++)
			{
				rechts();
				_delay_ms(10);
			}
		}
}
 
void ini(void)
{
	int pos=0;
	int maxSense=0;
 
	for(int curpos=0;curpos<i360;curpos++)
	{		
		int iLicht = lichtL();
		if(iLicht>maxSense)
		{
			maxSense=iLicht;
			pos=curpos;
		}
		rechts();
		_delay_ms(100);
	}
 
	while(pos>0)
	{
		rechts();
		pos--;
		_delay_ms(100);
	}
}
 
// ************** Function: LED (an, aus oder Angabe in ms) *****************
void led(int l) 
{
	if (l==1)      	// LED an
	{
		PORTB &= 0b111011;	//low
	}
	else if (l==0)  // LED aus
	{
		PORTB |= 0b000100;	// high
	}
	else    		// LED blitz
	{		
		PORTB &= 0b111011;	//low
		for (i=l/10; i>0; i--) _delay_ms(10);
		PORTB |= 0b000100;	// high
	}
}
 
// ************** MAIN ******************************************************
int main(void)
{
// ########## config #############
 
//       5  4    3    2   1  0
//      [X LDR1 LDR2 LED MB MA]
//      [X  E    E    A   A  A]
 
	DDRB  = 0b000111;        // Ausgang=1, Eingang=0
	PORTB = 0b000100;        // preset
 
	led(1000); _delay_ms(250);
 
// ########## bewegen ############
	ini();
	while(1)
	{
		if(lichtL() > lichtR() + toleranz)  	// wenn links heller
		{
			links();		// fahre links
		}
		else if(lichtR() > lichtL() + toleranz)		// wenn rechts heller
		{
			rechts();		// fahre rechts
		}else
		{
			// blinken
			led(10); _delay_ms(100); led(10); _delay_ms(100); led(10);
		}
		_delay_ms(80);
	}
	return 1;
}

[/showhide]

Download Programmcode und Hex Dateien

So, das sollte an Info schon reichen, um das Spielzeug nachzubauen, zu verbessern oder weiter zu entwickeln. Lass dich noch von meinem Demovideo inspirieren. Viel Spaß beim Spielen 🙂



Haftungsausschluss: Ich übernehme keinerlei Verantwortung für auftretende Schäden oder Folgeschäden bei der Anwendung und Nutzung meiner Anleitungen. Alle Angaben sind ohne Gewähr. Außerdem obliegt jedem Leser die Prüfung der rechtlichen Zulassung in seinem Land, das gilt insbesondere für TÜV-Freigaben von baulichen Veränderungen an Fahrzeugen und Einbau von Zubehör. Meine Artikel sind nichts weiter als eine Art Machbarkeitsstudie zu verstehen. Jeder Leser hat vorher selbst die Durchführbarkeit zu überprüfen.



Noch keine Kommentare

Schreibe einen Kommentar