Forum: Mikrocontroller und Digitale Elektronik Servo Ansteuern Frage


von Bert S. (kautschuck)


Lesenswert?

Hi,
Ich habe folgende Probleme beim Ansteuern einer Servo:

1.) Wenn ich die Funktion my_delay_us(y) verwende dreht sich die servo 
ruckartig im GUZ bis sie anstellt und nicht passiert mehr, bei 
_delay_us("zahl") klappt alles wunderbar.

2.) Wenn ich über UART einen Wert schicken möchte, dann löst es mir den 
Interrupt nonstop aus, obwohl ich das RXE in UCSRA wieder auf 0 stelle.
1
#include <avr/io.h>
2
#include <avr/delay.h>
3
#include <avr/interrupt.h>
4
5
#define F_CPU 1000000UL
6
#define BAUD 4800UL
7
#define MYUBRR ((F_CPU+BAUD*8)/(BAUD*16)-1)
8
9
#define USART_RXC_vect _VECTOR(11)
10
11
void init();
12
void USART_Init( unsigned int ubrr);
13
void USART_Transmit(unsigned char data);
14
void my_delay_us(uint16_t count);
15
16
uint8_t x = 150;
17
uint16_t y = 150;
18
19
ISR(USART_RXC_vect) {
20
  if(50<UDR && UDR<240)
21
    x =UDR;
22
  y = 10*x;    
23
  UCSRA &= ~(0b10000000); //Interrupt abschalten
24
  
25
}
26
27
int main(void)
28
{
29
  init();
30
    while(1)
31
    {
32
    for (uint8_t i = 0; i<50;i++)
33
    {
34
      PORTB = 0x01;
35
      _delay_us(1000); //delay should depends on y with my_delay_us(y)
36
      PORTB = 0x00;
37
      _delay_us(19000);
38
    } 
39
    
40
            
41
    for (uint8_t i = 0; i<50;i++)
42
    {
43
      PORTB = 0x01;
44
      _delay_us(2000);
45
      PORTB = 0x00;
46
      _delay_us(18000);  
47
    }        
48
    }
49
}
50
51
void init() {
52
  DDRB = 0x01;
53
  PORTB = 0x00;  
54
  USART_Init(MYUBRR);
55
  
56
}
57
58
void USART_Init( unsigned int ubrr)
59
{
60
61
  UBRRH = MYUBRR >> 8;
62
  UBRRL = MYUBRR & 0xFF;
63
64
  UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
65
66
  UCSRC = (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);
67
  
68
  sei();
69
}
70
71
void my_delay_us(uint16_t count) {
72
  while(count--) {
73
    _delay_us(1);
74
  }
75
}
76
77
void USART_Transmit( unsigned char data )
78
{
79
80
  while ( !( UCSRA & (1<<UDRE)) );
81
  UDR = data;
82
}

Jemand eine Idee an was sowas liegen kann?

Gruss Bert

von Peter II (Gast)


Lesenswert?

Bert Siegfried schrieb:
> Wenn ich die Funktion my_delay_us(y) verwende dreht sich die servo
> ruckartig im GUZ bis sie anstellt und nicht passiert mehr, bei
> _delay_us("zahl") klappt alles wunderbar.

_delay_us sollte man nur mit einer Konstanten verwenden, steht auch in 
der doku

Bert Siegfried schrieb:
> 2.) Wenn ich über UART einen Wert schicken möchte, dann löst es mir den
> Interrupt nonstop aus, obwohl ich das RXE in UCSRA wieder auf 0 stelle.

warum löst er überhaupt aus, du aktivierst ihn ja vorher gar nicht?

wenn das das ausschalten ist
1
UCSRA &= ~(0b10000000); //Interrupt abschalten
wo ist dann das einschalten?


Der ganze Ansatz mit dem delay wird nicht ordentlich funktionieren. Du 
muss den servo mit hilfe des Timer ansteuern.

von Bert S. (kautschuck)


Lesenswert?

Peter II schrieb:

> wenn das das ausschalten ist
>
1
> UCSRA &= ~(0b10000000); //Interrupt abschalten
2
>
> wo ist dann das einschalten?
>

Wenn ich doch mit z.B realterm ein Zeichen schicke, wird der Interrupt 
ausgelöst und das RXE bit in UCSRA wird auf 1 gesetzt.

Ja ich denke das mit Timern ist sicher die beste Variante, habe es nur 
mal mit den delays zum testen gemacht.

Gruss und Danke Bert.

von Thomas E. (picalic)


Lesenswert?

Peter II schrieb:
> _delay_us sollte man nur mit einer Konstanten verwenden, steht auch in
> der doku

macht er doch! In der Funktion "my_delay_us()" ruft er es mit der 
Konstanten "1" auf!
Allerdings ist es wohl etwas optimistisch gedacht, daß der Rest 
drumherum (while-Loop incl. Variable decrentieren) keine Rechenzeit 
beansprucht...

von Peter II (Gast)


Lesenswert?

Thomas Elger schrieb:
> macht er doch!

oder auch nicht

> Wenn ich die Funktion my_delay_us(y)

von Bert S. (kautschuck)


Lesenswert?

Peter II schrieb:
> Thomas Elger schrieb:
>> macht er doch!
>
> oder auch nicht
>
>> Wenn ich die Funktion my_delay_us(y)

Aber my_delay_us() ist ja meine eigene, in der ich dann immer
_delay_us(1) aufrufe, aber eben, mit timer ist das ganze natürlich viel 
besser.

Was aber genau bei den Interrupts das Problem ist, sehe ich einfach 
nicht.

von STK500-Besitzer (Gast)


Lesenswert?

1
 if(50<UDR && UDR<240)
2
    x =UDR;

UDR ist nur einmalig lesbar. Danach steht da das nächste empfangene Byte 
drin (oder wirres Zeug).

von Bert S. (kautschuck)


Lesenswert?

Ja, das schon, aber mein Problem ist, dass die ISR des Interruptvektor 
11, also die für rx interrupts nach dem senden eines Zeichens nonstopp 
ausgeführt wird, also nur noch Interrupts.

von Wolfgang (Gast)


Lesenswert?

Bert Siegfried schrieb:
> Aber my_delay_us() ist ja meine eigene, in der ich dann immer
> _delay_us(1) aufrufe, aber eben, mit timer ist das ganze natürlich viel
> besser.

Was meinst du, wie ungenau dein my_delay_us() mit dem ganzen 
Verwaltungskram ist? Der Simulator zeigt es dir taktgenau an. Oder nimm 
ein Oszi und guck dir das Ergebnis auf einem Pin an.

von STK500-Besitzer (Gast)


Lesenswert?

1
UCSRA &= ~(0b10000000); //Interrupt abschalten

Wenn das das Gleiche wie
1
UCSRA &= ~(1<<RXCIE); //Interrupt abschalten

heissen soll, dann ist das überflüssig (und unleserlich sowieso).
Es könnte natürlich auch
1
UCSRA &= ~(1<<RXCI); //Interrupt abschalten

heissen, was man aber nur weiß, wenn man sich das Datenblatt anguckt und 
die Bitposition auszählt.

Beides ist in diesem Zusammenhang aber eh falsch bzw. unnötig.

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.