Forum: Mikrocontroller und Digitale Elektronik ADC-Schrittmotor Atmega16


von Michi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Miteinander,

ich bräuchte aktuell mal etwas Hilfe bzw. jemanden der über meinen Code 
drüber schauen könnte, da ich momentan nicht weiterkomme.

Will einen Schrittmotor über ein A4988 betreiben, der Motor soll sich 
nach links oder rechts bewegen je nachdem welche LDR (PA0+PA1= mehr 
Licht bekommt.

Aktuell dreht sich der Motor zwar, aber nur in eine Richtung egal wie 
die zwei LDRs Licht bekommen oder abgedunkelt werden. Seit nicht zu hart 
zu mir bin recht neu dabei :-) hab aber irgendwie das Gefühl das ich 
irgendetwas banales übersehe.

Vielen Dank



Code:
1
#define F_CPU 1000000UL
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <util/delay.h>
5
6
7
8
int main(void)
9
{
10
  
11
  //Ausgänge und Eingänge Konfig
12
  
13
  DDRB |= (1 << PB0) | (1 << PB1) | (1 << PB2) | (1 << PB3) | (1 << PB4) | (1 << PB5) | (1 << PB6) | (1 << PB7);  // PB 0-7 auf Ausgang
14
  DDRA &= ~( (1 << PA0) | (1 << PA1) ); // PA 0 & 1 auf Eingang (LDRs)
15
  DDRD |= (1 << PD5) | (1 << PD6); //PD 5 und 6 auf Ausgang
16
17
  /*DDRD &= ~((1 << PD5) | (1 << PD6)); // PD 5 & 6 auf Eingang (Schalter) Wird erst später angewendet*/
18
  
19
20
  PORTB &= ~((1<<PB2) | (1<<PB3) | (1<<PB4) | (1<<PB5) | (1<<PB6) | (1<<PB7));  // PB 2 - 7 auf Low
21
22
  //ADC Setup
23
  
24
  ADMUX |= (1<<REFS0); // AVCC Refernz mit Kondensator an AREF PIN
25
  ADCSRA |= (1<<ADEN) |  (1<<ADPS2);  // ADC anschalten, Division Faktor 16
26
  
27
  //1 Konversion abwarten
28
  ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung
29
  while (ADCSRA & (1<<ADSC) ) {         // auf Abschluss der Konvertierung warten
30
  }
31
  
32
  
33
  
34
  
35
  //Hauptschleife
36
  
37
  while (1)
38
  {
39
    
40
    ADMUX &= ~(1<<MUX0); //ADC0
41
    
42
    ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung
43
    while (ADCSRA & (1<<ADSC) ) {         // auf Abschluss der Konvertierung warten
44
    }
45
    
46
    uint8_t LowR = ADCL;
47
    uint16_t  R_LDR = ADCH<<8 | LowR;
48
    ADCSRA &= ~(1<<ADEN);//ADC aus
49
    
50
    ADMUX |= (1<<MUX0); //ADC1
51
    
52
    
53
    ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung
54
    while (ADCSRA & (1<<ADSC) ) {         // auf Abschluss der Konvertierung warten
55
    }
56
    
57
    
58
    uint8_t LowL = ADCL;
59
    uint16_t  L_LDR = ADCH<<8 | LowL;
60
    ADCSRA &= ~(1<<ADEN); //ADC aus
61
    
62
    
63
    if(R_LDR > L_LDR){
64
      
65
      PORTD |= (1<<PD5); //Richtung rechts?
66
      PORTD |= (1<<PB6); //Step Puls an
67
      _delay_us(800);
68
      PORTB &= ~(1<<PD6);  //Step Puls aus
69
      _delay_us(800);
70
      
71
    }
72
    else{
73
      
74
      PORTD &= ~(1<<PD5); //Richtung links?
75
      PORTD |= (1<<PD6); //Step Puls an
76
      _delay_us(800);
77
      PORTD &= ~(1<<PB6);  //Step Puls aus
78
      _delay_us(800);
79
      
80
    }
81
    
82
  }
83
  
84
  }

: Bearbeitet durch User
von n8 (Gast)


Lesenswert?

Michi schrieb:
> ADMUX &= ~(1<<MUX0); //ADC0

ich würde den da explizit auf Kanal 0 setzen

ADMUX = 0;


Michi schrieb:
> ADMUX |= (1<<MUX0); //ADC1

ich würde den da explizit auf Kanal 1 setzen

ADMUX = 1;

Michi schrieb:
> ADCSRA &= ~(1<<ADEN);//ADC aus

Michi schrieb:
> ADCSRA &= ~(1<<ADEN); //ADC aus

ADC aus nicht machen.

Michi schrieb:
> uint8_t LowR = ADCL;
>     uint16_t  R_LDR = ADCH<<8 | LowR;
> [...]
> uint8_t LowL = ADCL;
>     uint16_t  L_LDR = ADCH<<8 | LowL;

hier reicht "uint16_t  R_LDR = ADC;" bzw. "uint16_t  L_LDR = ADC;"

von MaWin (Gast)


Lesenswert?

Eine PortB und PortD Verwirrung, PB6 und PORTB wohl falsch.
ADC aus klingt unpassend.

von Michi (Gast)


Lesenswert?

Hallo,

danke erstmal :-) den Fehler mit dem PORTD PB6 etc. hab ich schon 
korrigiert, danke den Rest versuche ich gleich heute Abend.

von Michi (Gast)


Lesenswert?

n8 schrieb:
> Michi schrieb:
>> ADMUX &= ~(1<<MUX0); //ADC0
>
> ich würde den da explizit auf Kanal 0 setzen
>
> ADMUX = 0;
>


Wird da aber nicht mit dem Befehl meine Referenzspannung

"ADMUX |= (1<<REFS0); // AVCC Refernz mit Kondensator an AREF PIN"

wieder auf 0 gesetzt ?

von Michi (Gast)


Lesenswert?

Hab jetzt alles einmal so umgesetzt aber er dreh sich leider immer noch 
nur in eine Richtung :-(.
Habe das Gefühl das er nie den Wert bekommt um sich in die andere 
Richtung zu drehen.

von Wolfgang (Gast)


Lesenswert?

Michi schrieb:
> Hab jetzt alles einmal so umgesetzt ...

Wenn du ein paar aussagekräftige Bezeichnungen für deine genutzten GPIOs 
verwendest (per #define), wird der Code auch lesbarer.

Nimm einfach mal eine LED (mit Vorwiderstand) und lass die am Steuerpin 
für DIR blinken. Wenn das funktioniert, sehen wir weiter.

von Michi (Gast)


Angehängte Dateien:

Lesenswert?

Sollte jetzt etwas übersichtlicher sein.
Leds sind dran beide leuchten, die dir LED fängt nur leicht an zu 
flackern wenn ich eine LDR mit einer Taschenlampe bestrahle.

An AREF ist ein 100 uf Kondesator dran

von Michi (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich komme leider nicht weiter, habe das Programm umgeschrieben und noch 
ein LC-Display angehängt um die Werte auch mal zu sehen die der ADC 
auswirft.
Der ADC soll jetzt 20 Werte in ein Array schreiben und danach den 
Mittelwert bilden. (Bin mir nicht ganz sicher ob das ganze so richtig 
umgesetzt ist) aber die Werte die mir angezeigt werden schwanken soweit 
ich das erkennen kann zwichen 50 und 230 je nachdem ob ich eine 
Taschenlampe auf die LDRs halte oder nicht, das wichtigste aber ist dass 
sich eigentlich meistens beide Werte ändern AUCH wenn ich nur eine LDR 
mit der Lampe anstrahle.
(Das hat er aber auch schon ohne das Array-Mittelwert-Ding gemacht)

Irgendwie habe ich das Gefühl das der ADC einfach von mir falsch 
"eingestellt/konfiguriert" ist ? Wäre super wenn jemand drüber gucken 
könnte, ich glaube ich sehe einfach den Wald vor lauter Bäumen nicht 
oder bin einfach zu doof
:-(

Vielen Dank, anbei nochmal mein Programm aktuell.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

> ADMUX = 0b01000010; //ADC1 Ein
Hier wählst du ADC2 an Port PA2

> ADMUX = 0b01000100; //ADC2 Ein
Und hier dann ADC4 an Port PA4

Ich vermute mal, das das nicht dein Ziel war. Möchtest du ADC1 und ADC2 
auswählen, verwendest du besser 0b01000001 resp. 0b01000010

Siehe dazu auch die Tabelle im Datenblatt bei der Beschreibung des ADMUX 
Registers.

Michi schrieb:
> An AREF ist ein 100 uf Kondesator dran

Na, das wollen wir mal nicht hoffen. Besser ist ein 100nF = 0,1µF.

: Bearbeitet durch User
von Michi (Gast)


Lesenswert?

Matthias S. schrieb:
>> ADMUX = 0b01000010; //ADC1 Ein
> Hier wählst du ADC2 an Port PA2
>
>> ADMUX = 0b01000100; //ADC2 Ein
> Und hier dann ADC4 an Port PA4
>

>
> Siehe dazu auch die Tabelle im Datenblatt bei der Beschreibung des ADMUX
> Registers.
>
> Michi schrieb:
>> An AREF ist ein 100 uf Kondesator dran
>
> Na, das wollen wir mal nicht hoffen. Besser ist ein 100nF = 0,1µF.

Oh ja Danke :-| , hab ich jetzt so geändert, trotzdem verändern sich 
immer noch beide Werte auch wenn ich nur eine LDR anleuchte, egal welche 
beide Werte gehen runter ? :-(

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Michi schrieb:
> egal welche
> beide Werte gehen runter

Mal doch mal bitte deinen Schaltplan auf. Ich gebe zu, das es manchmal 
verwirrend ist, Pinnummer, Portpin und ADC Kanal in den Griff zu 
bekommen - wir hier im Elektronikforum finden Schaltpläne aber immer 
noch am besten.
Eine gute Kanaltrennung bekommt man übrigens, wenn man an allen 
benutzten ADC Eingängen einen kleinen Kondensator gegen Masse schaltet. 
Da machen sich 1nF - 10nF recht gut.

von Michi (Gast)


Lesenswert?

Hab es einigermaßen hinbekommen :-))) vielen vielen Dank an alle 
ersteinmal.
Denke dass ein zwei Kleinigkeiten auf dem Testboard noch nicht ganz 
"perfekt" angeschlossen waren.

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.