Forum: Mikrocontroller und Digitale Elektronik MD25-Motor mit RN-Control V1.4 (Atmega32) angesteuert dreht sich nicht


von sps (Gast)


Lesenswert?

Hallo Leute,
ich habe ein 
RN-Controllerhttp://www.robotikhardware.de/download/rncontrol14.pdf und 
der Motortreiber(MD25). Nun habe ich die PORTC :PC0 ,PC1 und belibiege 
GND mit dem I2C vom Treiber verbunden und auch die Motoren EMG30 an den 
Treiber angeschlossen.  Jetzt habe ich das folgende 
Demo-Programm(http://www.rn-wissen.de/index.php/RN-Control_Demprogramm_in_C) 
in Controller geflasht habe nur die dioden beim Drücken von Taste 3 
laufen(Lauflicht) und beim Drücken von Tast 2 passiert gar nix mit dem 
Motor.

Warum tun die Motor gar nix, was kann der Fehler sein???

Danke in Vorraus.

von sps (Gast)


Lesenswert?

das code:
1
/*
2
###################################################
3
rncontrol.h
4
5
Diese Header-Datei stellt grundlegende Funktionen für das RN-Control 1.4 in C zur Verfügung.
6
7
Autor: Georg Richter
8
#######################################################
9
*/
10
11
12
#include <util/delay.h>
13
14
15
16
/*### waitms - Programm pausieren lassen ###*/
17
18
/*Die Funktion lässt circa so viele Millisekunden verstreichen, wie angegeben werden.
19
Angepasst auf das RN-Control 1.4 mit 16 MHz-Quarz!
20
Vorsicht, Wert ist nur experimentell angenähert, nicht exakt berechnet!*/
21
22
void waitms(uint16_t ms)
23
{
24
  for(; ms>0; ms--)
25
  {
26
    uint16_t __c = 4000;
27
    __asm__ volatile (
28
      "1: sbiw %0,1" "\n\t"
29
      "brne 1b"
30
      : "=w" (__c)
31
      : "0" (__c)
32
    );
33
  }
34
}
35
36
37
38
39
/*### Ports setzen ###*/
40
41
//Ports auf HIGH setzen
42
static inline void setportaon(const uint8_t n)
43
{PORTA |= (1<<n);}  //set PORTA.n high
44
45
static inline void setportbon(const uint8_t n)
46
{PORTB |= (1<<n);}  //set PORTB.n high
47
48
static inline void setportcon(const uint8_t n)
49
{PORTC |= (1<<n);}  //set PORTC.n high
50
51
static inline void setportdon(const uint8_t n)
52
{PORTD |= (1<<n);}  //set PORTD.n high
53
54
55
56
//Ports auf LOW setzen
57
static inline void setportaoff(const uint8_t n)
58
{PORTA &= ~(1<<n);}  //set PORTA.n low
59
60
static inline void setportboff(const uint8_t n)
61
{PORTB &= ~(1<<n);}  //set PORTB.n low
62
63
static inline void setportcoff(const uint8_t n)
64
{PORTC &= ~(1<<n);}  //set PORTC.n low
65
66
static inline void setportdoff(const uint8_t n)
67
{PORTD &= ~(1<<n);}  //set PORTD.n low
68
69
70
71
72
73
/*### Senden per USART - RS232-Kommunikation ###*/
74
75
/*Zum senden von Zeichen im Hauptprogramm entweder
76
77
char irgendwas[] = "meintext";
78
sendUSART(irgendwas);
79
80
oder direkt
81
82
sendUSART("meinText");
83
84
verwenden.*/ 
85
86
void init_USART(void)
87
{
88
  UCSRB |= (1<<TXEN);  //UART TX (Transmit - senden) einschalten
89
  UCSRC |= (1<<URSEL)|(3<<UCSZ0);  //Modus Asynchron 8N1 (8 Datenbits, No Parity, 1 Stopbit)
90
  UBRRH = 0;        //Highbyte ist 0
91
  UBRRL = 103;  //Lowbyte ist 103 (dezimal) -> (Frequenz_in_Hz / (Baudrate * 16)) - 1 <- Quarfrequenz = 16*1000*1000 Hz!!!!
92
}
93
94
95
96
void sendchar(unsigned char c)
97
{
98
  while(!(UCSRA & (1<<UDRE))) //Warten, bis Senden möglich ist
99
  {
100
  }
101
  
102
  UDR = c; //schreibt das Zeichen aus 'c' auf die Schnittstelle
103
}
104
105
106
107
void sendUSART(char *s) //*s funktiniert wie eine Art Array - auch bei einem String werden die Zeichen (char) einzeln ausgelesen - und hier dann auf die Sendeschnittstelle übertragen
108
{
109
  while(*s)
110
  {
111
  sendchar(*s);
112
  s++;
113
  }
114
}
115
116
117
118
119
120
/*### ADC-Ansteuerung ###*/
121
122
uint16_t adcwert(uint8_t kanal)
123
{
124
  uint16_t wert = 0; //Variable für Ergebnis deklarieren
125
126
  ADCSRA = (1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);  //ADEN aktiviert überhaupt erst den internen ADC-Wandler, ADPS2 bis ADPS0 stellen den verwendeten Prescaler ein, denn die Wandlerfrequenz muss immer zwischen 50 und 200 kHz liegen! Der Prescaler muss bei 16MHz also zwischen 80 und 320 eingestellt werden, als einzige Möglichkeit bleibt hier 128 (=alle auf 1).   
127
128
  ADMUX = kanal;
129
  //ADMUX = (1<<REFS1)|(1<<REFS0); //Einstellen der Referenzspannung auf "extern", also REFS1 und REFS0 auf "0" - daher auskommentierte Zeile
130
  
131
  ADCSRA |= (1<<ADSC);  //nach Aktivierung des ADC wird ein "Dummy-Readout" empfohlen, man liest also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen"      
132
    while(ADCSRA & (1<<ADSC)) {} //auf Abschluss der Konvertierung warten
133
  wert = ADCW;  //ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten Wandlung nicht übernommen.
134
 
135
  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
136
  wert = 0; 
137
  for(uint8_t i=0; i<4; i++)
138
  {
139
    ADCSRA |= (1<<ADSC);   //eine Wandlung "single conversion" starten
140
    while(ADCSRA & (1<<ADSC)) {}   //auf Abschluss der Konvertierung warten
141
    wert = wert + ADCW;   //Wandlungsergebnisse aufaddieren
142
    }
143
  
144
  ADCSRA &= ~(1<<ADEN);  //ADC deaktivieren
145
 
146
  wert = wert/4;    //Durchschnittswert bilden
147
 
148
  return wert;
149
}
150
151
152
153
154
155
/*### Buttonabfrage ###*/
156
157
uint8_t button(void)
158
{
159
  uint8_t taste = 0;   //Variable für Nummer des Tasters
160
  uint16_t analog7 = adcwert(7);  //Wert des Ports
161
  
162
  setportaon(7);    //Ohne das hier "flackern" die Werte aus irgend einem Grund -> es werden mitunter Tasten erkannt, die gar nicht gedrückt wurden oder das Programm bleibt für einige Sekunden "hängen"
163
  waitms(1);
164
  setportaoff(7);
165
  
166
  //Abfrage des gedrückten Tasters - um Störungen zu vermeiden wurden
167
        //die Bereiche sehr eng gefasst, sollten bei Bedarf an jedes Board extra angepasst werden.
168
  if((analog7>=337) && (analog7<=343)) {taste = 1;}
169
  else if((analog7>=268) && (analog7<=274)) {taste = 2;}
170
  else if((analog7>=200) && (analog7<=206)) {taste = 3;}
171
  else if((analog7>=132) && (analog7<=138)) {taste = 4;}
172
  else if((analog7>=64) && (analog7<=70)) {taste = 5;}
173
  else {}
174
  
175
  return taste;
176
}
177
178
179
180
181
/*### Sound durch den Speaker ausgeben ###*/
182
183
/*i wird immer um das doppelte der Tonhöhe hochgezählt. Grund: Um so tiefer
184
der Ton, desto größer ist "hoehe" -> desto länger sind die Pausenzeiten pro
185
"Tonschwingung". Dadurch würden tiefe Töne immer länger werden, was durch
186
diese Funktion abgefangen wird. Alle Töne mit der Länge x werden auch
187
ca x ms lang gespielt. Vernachlässigt wird hierbei jedoch die benötigte Zeit
188
zum Umschalten der Pins und Hochzählen der Schleife, um so höher der Ton, 
189
desto länger wird er also real gespielt, weil öfter gezählt und umgeschaltet
190
werden muss. Bei hoehe=1 benötigt ein Ton etwa das 1,733-fache der Zeit, die
191
als Dauer angegeben wird; bei hoehe=30 wird sie hingegen beinahe eingehalten.
192
Der Multiplikator von 15 in der Länge gleicht die seltsame Dauer, die die
193
Delay-Schleife hat, aus (die kommt aus irgend einem Grund nicht mal annähernd
194
an Millisekunden heran).*/
195
196
197
void sound(uint8_t hoehe, uint16_t laenge)
198
{
199
  for(uint16_t i=0; i<laenge*15; i=i+(2*hoehe))
200
  {
201
    setportdon(7);
202
    _delay_loop_2(hoehe<<7); // 0,032ms*hoehe warten bei einem 16 MHz-Quarz
203
    setportdoff(7);      // (hoehe<<7) ist eine effizientere Schreibweise von hoehe*128
204
    _delay_loop_2(hoehe<<7);
205
  }
206
}
207
208
209
210
211
212
/*### PWM-Routinen zur Motoransteuerung ###*/
213
214
void init_timer1(void)  //Initialisierung des Timers für Erzeugung des PWM-Signals
215
{
216
   /* normale 8-bit PWM aktivieren (nicht invertiert),
217
   Das Bit WGM10 wird im Datenblatt auch als PWM10 bezeichnet */
218
   TCCR1A = (1<<COM1A1)|(1<<COM1B1)|(1<<WGM10);
219
220
   /* Einstellen der PWM-Frequenz auf 14 kHz ( Prescaler = 1 ) */
221
   TCCR1B = (1<<CS10);
222
223
   /* Interrupts für Timer1 deaktivieren
224
   Achtung : Auch die Interrupts für die anderen Timer stehen in diesem Register */
225
   TIMSK &= ~0x3c;
226
}
227
228
229
230
void setPWMlinks(uint8_t speed) //Geschwindigkeit linker Motor
231
{OCR1BL = speed;}
232
233
void setPWMrechts(uint8_t speed) //Geschwindigkeit rechter Motor
234
{OCR1AL = speed;}
235
236
237
238
void Mlinkszur(void)  //Uhrzeigersinn
239
{PORTC |= (1<<PC6); PORTC &= ~(1<<PC7);}
240
241
void Mlinksvor(void)  //mathematischer Drehsinn
242
{PORTC &= ~(1<<PC6); PORTC |= (1<<PC7);}
243
244
void Mlinksstop(void)  //aus
245
{ PORTC &= ~(1<<PC6); PORTC &= ~(1<<PC7);}
246
247
248
249
void Mrechtsvor(void)  //Uhrzeigersinn
250
{PORTB |= (1<<PB0); PORTB &= ~(1<<PB1);}
251
252
void Mrechtszur(void)  //mathematischer Drehsinn
253
{PORTB &= ~(1<<PB0); PORTB |= (1<<PB1);}
254
255
void Mrechtsstop(void)  //aus
256
{PORTB &= ~(1<<PB0); PORTB &= ~(1<<PB1);}  
257
258
[bearbeiten]
259
Das C Demoprogramm
260
261
/*
262
###################################################
263
RNControl-Test.c
264
265
Aufgabe:
266
 Dieses Testprogramm testet gleich mehrere Eigenschaften auf dem Board
267
 Den verschiedenen Tasten sind bestimmte Funktionen zugeordnet
268
 Taste 1: Zeigt Batteriespannung über RS232 an
269
 Taste 2: Angeschlossene Motoren beschleunigen und abbremsen
270
 Taste 3: Einige Male Lauflicht über LED´s anzeigen. Am I2C-Bus
271
          darf in diesem Moment nichts angeschlossen sein
272
 Taste 4: Zeigt analoge Messwerte an allen Port A PIN´s über RS232 an
273
 Taste 5: Zeigt digitalen I/O Zustand von PA0 bis PA5 an
274
275
276
 Sehr gut kann man aus dem Demo auch entnehmen wie Sound ausgegeben wird,
277
 wie Tasten abgefragt werden und wie Subroutinen und Funktionen angelegt werden
278
279
Autor: Georg Richter
280
#######################################################
281
*/
282
283
284
285
286
287
#include <stdlib.h> 
288
#include <avr/io.h>
289
#include "rncontrol.h"
290
291
292
293
294
295
/*### Variablen ###*/
296
const float referenzspannung = 0.0048828125;  //Referenzwert zur Multiplikation mit den Werten der Analogports (0...1023), um auf die Voltzahl zu kommen (0...5). Ergibt sich aus 5/1024.
297
uint16_t analog; //Variable für jeweils an einem Analogport gemessenen Wert, um nicht für eine Ausgabe mehrere Messungen durchführen zu müssen.
298
char wort[5];  //Zahlen (Integer und Float) müssen vor der Ausgabe per RS232 in ASCII-Zeichen konvertiert werden, für die ein Speicher benötigt wird.
299
300
301
302
303
304
/*### Batteriespannung ###*/
305
void Batteriespannung(void)
306
{
307
  sendUSART("Analog6 = "); analog = adcwert(6);
308
  utoa(analog, wort, 10);  sendUSART(wort); sendUSART(" = ");
309
  dtostrf(analog*referenzspannung, 11, 8, wort);  sendUSART(wort); sendUSART(" Volt\r\n");
310
  dtostrf(adcwert(6)*referenzspannung*5.66804, 11, 8, wort);
311
  sendUSART("Batteriespannung = "); sendUSART(wort); sendUSART(" Volt\r\n\n\n\n");
312
  waitms(300);
313
}
314
315
316
317
318
319
/*### Motortest ###*/
320
void Motortest(void)
321
{
322
  Mlinksvor();
323
  Mrechtsvor();
324
325
  setPWMlinks(0);
326
  setPWMrechts(0);
327
  waitms(40);
328
329
  for(uint8_t i=0; i<255; i=i+5)
330
  {
331
    setPWMlinks(i);
332
    setPWMrechts(i);
333
    waitms(40);
334
  }
335
336
  setPWMlinks(255);
337
  setPWMrechts(255);
338
  waitms(40);
339
340
  for(uint8_t i=255; i>0; i=i-5)
341
  {
342
    setPWMlinks(i);
343
    setPWMrechts(i);
344
    waitms(40);
345
  }
346
347
  setPWMlinks(0);
348
  setPWMrechts(0);
349
350
  Mlinksstop();
351
  Mrechtsstop();
352
  waitms(300);
353
}
354
355
356
357
358
359
/*### LED-Lauflicht ###*/
360
void Lauflicht(void)
361
{
362
  for(uint8_t i=0; i<10; i++)
363
  {
364
  setportcoff(0);
365
  waitms(150);
366
  setportcon(0);
367
  setportcoff(1);
368
  waitms(150);
369
  setportcon(1);
370
  setportcoff(2);
371
  waitms(150);
372
  setportcon(2);
373
  setportcoff(3);
374
  waitms(150);
375
  setportcon(3);
376
  setportcoff(4);
377
  waitms(150);
378
  setportcon(4);
379
  setportcoff(5);
380
  waitms(150);
381
  setportcon(5);
382
  waitms(300);
383
  }
384
}
385
386
387
388
389
390
/*### Analogwerte ###*/
391
void Analogwerte(void)
392
{
393
  //Alle internen Pullups an, ausgenommen Port A3 und Batteriespannung/Taster (A6 und A7). Da A3 aber nun auch nicht auf GND liegt, ergibt sich ein "Rauschen", der Wert variiert mit jeder Messung mehr oder weniger stark.
394
  setportaon(0);
395
  setportaon(1);
396
  setportaon(2);
397
  setportaoff(3);
398
  setportaon(4);
399
  setportaon(5);
400
  
401
  for(uint8_t i=0; i<8; i++)
402
  {
403
    analog = adcwert(i);  //Messung Analogport [i]
404
    utoa(i, wort, 10); sendUSART("Analog"); sendUSART(wort); sendUSART(" = "); //Ausgabe: "Analog[i] = "
405
    utoa(analog, wort, 10);  sendUSART(wort); sendUSART(" = "); //Ausgabe: "[Analogwert] = "
406
    dtostrf(analog*referenzspannung, 11, 8, wort);  sendUSART(wort); sendUSART(" Volt\r\n"); //Ausgabe: "[Reale Voltzahl] Volt[Umbruch]"
407
  }
408
  
409
  sendUSART("\n\n\n");
410
  waitms(300);
411
}
412
413
414
415
416
417
/*### Digitalwerte ###*/
418
void Digitalwerte(void)
419
{
420
  //Einige interne Pullups an, andere aus -> gibt bei einigen "Rauscheffekt", mal misst er "high", mal "low" und mal irgendwas dazwischen "?".
421
  //Ein kleines Stückchen Draht an einem der Ports wirkt wahre Wunder, was das Rauschen betrifft -> viel öfter "low" dabei als ohne. Nachteil: Die Tastenerkennung funktioniert kaum noch.
422
  setportaoff(0);
423
  setportaon(1);
424
  setportaoff(2);
425
  setportaon(3);
426
  setportaon(4);
427
  setportaon(5);
428
  
429
  for(uint8_t i=0; i<8; i++)
430
  {
431
    utoa(i, wort, 10); sendUSART("Digital"); sendUSART(wort); sendUSART(" = ");  //Ausgabe: "Digital[i] = "
432
    if (PINA & (1<<i)) {sendUSART("high");} else {sendUSART("low");}  //Abgleich des Zustandes - Ausgabe: "high" oder "low"
433
    sendUSART("\r\n");
434
  }
435
  
436
  sendUSART("\n\n\n");
437
  waitms(300);
438
}
439
440
441
442
443
444
/*### Hauptschleife ###*/
445
int main(void)
446
{
447
448
  /*###Initialisierungsphase###*/
449
450
  //Pins bzw. Ports als Ein-/Ausgänge konfigurieren
451
  DDRA |= 0x00;  //00000000 -> alle Analogports als Eingänge
452
  DDRB |= 0x03;  //00000011 -> PORTB.0 und PORTB.1 sind Kanäle des rechten Motors
453
  DDRC |= 0xFF;  //11111111 -> PORTC.6 und PORTC.7 sind Kanäle des linken Motors, Rest sind LEDs für Lauflicht
454
  DDRD |= 0xB0;  //10110000 -> PORTD.4 ist PWM-Kanal des linken Motors, PORTD.5 des rechten
455
  
456
  //Initialisierungen
457
  setportcon(0); setportcon(1); setportcon(2); setportcon(3); setportcon(4); setportcon(5); //LEDs ausschalten
458
  setportdoff(7);  //Speaker aus
459
  init_timer1();  //Initialisierung Timer für PWM
460
  init_USART();  //USART konfigurieren
461
462
463
464
  /*###Hauptschleife###*/
465
  sound(6, 270); //Startmelodie
466
  sound(8, 270);
467
  sound(11, 270);
468
  sound(7, 270);
469
  waitms(10);
470
  sound(7, 270);
471
  sound(6, 270);
472
  sound(11, 540);
473
  sendUSART("\r\n\n\n"); //Sendet einen kleinen Begrüßungstext. "\r" setzt den Cursor wieder auf Zeilenanfag, "\n" beginnt dann die nächste Zeile
474
  sendUSART("**** RN-CONTROL 1.4 *****\r\n");
475
  sendUSART(" \r\n");
476
  sendUSART("Fuer C umgeschrieben Version des mitgelieferten\r\n");
477
  sendUSART("Bascom-BASIC Beispielprogramms inkl. eigener\r\n"); 
478
  sendUSART("Header-Datei mit wichtigen Grundfunktionen.\r\n");
479
  sendUSART(" \r\n");
480
  sendUSART("Vielen Dank an die RN-Community fuer ihre Hilfe!\r\n\n\n\n");
481
482
483
484
  Mlinksstop();
485
  Mrechtsstop();
486
487
488
  setPWMlinks(0);
489
  setPWMrechts(0);
490
491
492
  while(1)
493
  {
494
    switch(button())
495
    {
496
      case 1: Batteriespannung(); break;
497
      case 2: Motortest(); break;
498
      case 3: Lauflicht(); break;
499
      case 4: Analogwerte(); break;
500
      case 5: Digitalwerte(); break;
501
      default: break;
502
    }
503
  }
504
  
505
  
506
  return 0;
507
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.