Hallo liebes Forum,
ich möchte gerne die HIGH Pulslänge eines Modellbau Servo Signals messen
und daraufhin LEDs ansteuern. Ich versuche aktuell von der Arduino IDE
aufs Atmel Studio umzusteigen. In der Arduino IDE gibt es ja die
PulseIn() Funktion. Jetzt hab ich mal im Internet nach einem Code fürs
Atmel Studio gesucht und einen gefunden...
1
#define F_CPU 8000000UL //internal 8MHz
2
#include<avr/io.h>
3
#include<util/delay.h>
4
5
6
unsignedlongrc_value;
7
8
intmain(void)
9
{
10
DDRD=(0<<PD2);// port pd2 input rc signal
11
DDRD=(1<<PD6);// port , output led
12
13
//PORTD = (1<<PD6); //test function led
14
//char rc_pin_state = (PIND & (1<<PD2)); // read state of pin pd2 , put state variable
15
16
while(1)
17
{
18
charrc_pin_state=(PIND&(1<<PD2));
19
20
//timeout zone
21
unsignedlongnumloops=0;
22
unsignedlongmaxloops=500000;
23
unsignedlongwidth=0;
24
// wait previous pulse end
25
while(rc_pin_state==1)
26
{
27
rc_pin_state=(PIND&(1<<PD2));//keep reading pin until changes state
28
if(numloops++==maxloops)break;
29
}
30
// wait pulse start
31
while(rc_pin_state==0)
32
{
33
rc_pin_state=(PIND&(1<<PD2));//keep reading pin until changes state
34
if(numloops++==maxloops)break;
35
}
36
37
// wait pulse stop @ here measuring pulse width = incrementing width value 1 each cycle. atmega328 1 micro second equal 16 cycles.
38
while(rc_pin_state==1)
39
{
40
rc_pin_state=(PIND&(1<<PD2));
41
if(numloops++==maxloops)break;
42
width++;
43
}
44
45
rc_value=width/4;
46
47
48
if(rc_value>=0&&rc_value<1600)
49
{
50
PORTD=(1<<PD6);// turn led on
51
}
52
53
/*else if(rc_value > 1600 && rc_value < 2200)
54
{
55
PORTD = (0<<PD6); // turn led off
56
}*/
57
}
58
}
Hab den Code ausprobiert, aber er funktioniert nicht. Vielleicht kann
mir da jemand weiterhelfen oder hatte schon mal ein ähnliches Projekt...
Schon mal Danke im Voraus!
Zählschleifen sind immer Mist, Du hast keinerlei Kontrolle über deren
reale Laufzeit.
Nimm die Input Capture Funktion.
Und schließe ne UART oder ein LCD zum Anzeigen der Meßwerte an.
l. w. schrieb:> Hab den Code ausprobiert, aber er funktioniert nicht
Natürlich nicht.
width sollte man vor dem Zählen mal auf 0 setzen, und ob dein maxloops
vorher nicht zum break führt weiss man auch nicht.
Wieso width gerade bis 6400 zählen soll weiss auch keiner, einen
stabilen Bezug zu einem Zeitgeber hat dein Programm ja nicht, hängt ganz
von den Vompilereinstellungen zu Optimierungen ab.
So geht es also schon mal nicht.
Ob man unbedingt gleich Input Capture mit Interrupts macht, oder einfach
nur den Timer Zählerregister ausliest um zu erfahren, wie lange etwas
gedauert hat, ist egal.
l. w. schrieb:> ich möchte gerne die HIGH Pulslänge eines Modellbau Servo Signals messen
siehe Anhang wie man es machen kann.Ist zwar fuer einen Pic aber dies
umzusetzen auf Atmal uc's sollte kein Problem sein
MaWin schrieb:> Ob man unbedingt gleich Input Capture mit Interrupts macht, oder einfach> nur den Timer Zählerregister ausliest um zu erfahren, wie lange etwas> gedauert hat, ist egal.
Ich würde im ersten Anlauf einfach den Eingang pollen, dann den
Zeitstempel aus dem Timer lesen und eine Differenz berechnen. Etwa so:
1
main()
2
charrcpinold,rcpin;
3
unsignedlongrisetime,pulsdauer;
4
:
5
while(1){
6
:
7
rcpin=(PIND&(1<<PD2));
8
if(rcpin!=rcpinold){// Flanke?
9
if(rcpin){// steigende Flanke
10
risetime=lesetimeraus();
11
}
12
else{// fallende Flanke --> Pulsdauer berechnen
13
pulsdauer=lesetimeraus()-risteime;
14
}
15
}
16
rcpinold=rcpin;
17
:
18
}
19
}
Merke: man setzt einen Zähler nie zurück. Es sei denn, man weiß genau,
was man da tut und kann die Folgen abschätzen.
Toxic schrieb:> l. w. schrieb:>> ich möchte gerne die HIGH Pulslänge eines Modellbau Servo Signals messen> siehe Anhang wie man es machen kann.I
High-Zeit != Periodendauer ;-)
@Lothar M.
Kannst du mir bei der lesetimeraus() Funktion noch weiterhelfen. Hab mir
das Datenblatt des ATmega328 jetzt ne Zeit lang angeschaut und auch
schon ein bisschen herumprobiert aber hab da zu wenig Grundwissen zu
Timer und Registern, dass ich das hinbekomme. Wahrscheinlich sind es nur
ein paar Zeilen Code. Vlt kann mir da noch jemand weiterhelfen.
Schon mal danke !
Hallo zusammen,
ich hoffe ich werde nicht aus dem Forum verjagt, wenn ich dieses alte
Thema wieder ausgrabe. ;-)
Ich möchte das gleiche machen wie der Eröffner des Beitrags.
Idee: 16 bit Variable über Timer mit 1 MHz zählen lassen. Bei steigender
Flanke (Erkennung über INT0) Variable löschen und bei fallender Flanke
der Hauptschleife sagen, dass der Wert jetzt weiter verarbeitet werden
kann.
Mein Code sieht folgendermaßen aus:
1
#include<avr/io.h>
2
#include<avr/interrupt.h>
3
#include<util/delay.h>
4
#include<stdio.h>
5
#include<stdlib.h>
6
#include<util/atomic.h>
7
8
/*-------- Define --------*/
9
#define FOSC 16000000 //Clock Speed
10
#define BAUD 19200 //Debug
11
#define MYUBRR FOSC/16/BAUD-1
12
13
#define LED_PORT PC0
14
#define LED_ON PORTC |= (1 << LED_PORT)
15
#define LED_OFF PORTC &= ~(1 << LED_PORT)
16
17
#define RC_RECEIVER_PORT PD2
18
#define RISING_EDGE PIND & (1 << RC_RECEIVER_PORT)
19
20
/*Variablen*/
21
volatileuint16_tThrottle;
22
volatileuint16_tmicros;
23
24
volatileuint8_tpwm_ready=0;
25
volatileuint16_tpwm_duty_cycle;
26
volatileuint8_tcount;
27
volatileuint8_toverflows=0;
28
29
voidUSART_Init(unsignedintubrr)
30
{
31
/*Set baud rate */
32
UBRR0H=(unsignedchar)(ubrr>>8);
33
UBRR0L=(unsignedchar)ubrr;
34
/*Enable receiver and transmitter */
35
UCSR0B=(1<<RXEN0)|(1<<TXEN0);
36
/* Set frame format: 8data, 1stop bit */
37
UCSR0C=(1<<UCSZ01)|(1<<UCSZ00);
38
}
39
40
voiddebug_transmit(unsignedchardata)
41
//Nur für Debug
42
{
43
// Wait for empty transmit buffer
44
while(!(UCSR0A&(1<<UDRE0)));
45
// Put data into buffer, sends the data
46
UDR0=data;
47
//return 0;
48
}
49
50
voiddebug_puts(char*s)
51
{
52
while(*s)
53
{// so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)"
54
debug_transmit(*s);
55
s++;
56
}
57
}
58
59
voidpin_change_init(void)
60
{
61
EICRA=(1<<ISC00);
62
EIMSK=(1<<INT0);
63
}
64
65
voidPWM_Timer0_init(void)
66
{
67
TCCR0A=(1<<COM0A1)|(1<<COM0A0)|(1<<COM0B1)|(1<<COM0B0)|(1<<WGM01)|(1<<WGM00);//Clear OC0A/OC0B on Compare Match, set OC0A/OC0B at BOTTOM (inverting mode) Fast PWM, Top=0xFF
68
TCCR0B=(1<<CS01);//Prescaler = 8 --> 10 kHz für Motoren
69
OCR0A=0;//Motor1 aus
70
OCR0B=0;//Motor2 aus
71
}
72
73
voidPWM_Timer2_init(void)
74
{
75
TCCR2A=(1<<COM2A1)|(1<<COM2A0)|(1<<COM2B1)|(1<<COM2B0)|(1<<WGM21)|(1<<WGM20);//Clear OC0A/OC0B on Compare Match, set OC0A/OC0B at BOTTOM (inverting mode) Fast PWM, Top=0xFF
76
TCCR2A=(1<<CS21);//Prescaler = 8 --> ca. 10 kHz für Motoren
77
OCR2A=0;//Motor1 aus
78
OCR2B=0;//Motor2 aus
79
}
80
81
voidPPM_Counter_Timer1_init(void)
82
//Interrupt über CTC, ISR zählt mit 1 MHz
83
{
84
85
TCNT1=0;//Rücksetzen des Timers
86
OCR1A=16;// 1MHz
87
TCCR1B=(1<<WGM12);//CTC Modus
88
TCCR1B|=(1<<CS10);//Timer an / Kein Prescaler
89
TIMSK1=(1<<OCIE1A);//Timer/Counter1, Output Compare A Match Interrupt Enable
90
}
91
92
ISR(INT0_vect)
93
//ISR für Pin Change
94
{
95
// interrupt service routine for pin change interrupt
96
if(RISING_EDGE){// check if rising edge pin change interrupt (beginning of servo pulse)
97
98
micros=0;// reset counter
99
LED_ON;
100
return;
101
}
102
103
// only reached when falling edge detected (end of servo pulse)
104
105
Throttle=micros;// take timer value to global variable
106
pwm_ready=1;
107
LED_OFF;
108
}
109
110
ISR(TIMER1_COMPA_vect)
111
//Interrupt 1 MHz, läuft
112
{
113
micros++;
114
}
115
116
intmain()
117
118
{
119
charBuffer[12];
120
uint16_tThrottle_l;
121
122
DDRD=(1<<DDD6)|(1<<DDD5)|(1<<DDD3);//Ausgänge
123
//DDRD |= (1<<DDD1); //Onboard LED, für TX auskommentieren
124
DDRC=(1<<DDC1)|(1<<DDC0);//Ausgänge
125
126
USART_Init(MYUBRR);
127
_delay_ms(10);
128
129
debug_puts("Start\r\n");//Debug
130
debug_puts("Init Timers\r\n");//Debug
131
132
pin_change_init();
133
PPM_Counter_Timer1_init();
134
PWM_Timer0_init();
135
PWM_Timer2_init();
136
137
sei();
138
139
//Main
140
while(1)
141
{
142
if(pwm_ready)
143
{
144
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
145
{
146
Throttle_l=Throttle;
147
}
148
utoa(Throttle_l,Buffer,10);
149
debug_puts(Buffer);//Debug
150
debug_puts("\r\n");
151
pwm_ready=0;
152
}
153
154
}
155
}
Basis ist von hier:
https://github.com/chiefenne/ATTINY85-RC-Receiver-Decoder . Ich verwende
allerdings einen ATmega 328 p in der finalen Version mit 20 MHz (Pololu
Baby Orangutan) und hier einen 16 bit Timer statt dem 8 bit Timer. Der
Code ist für 16 MHz.
Mein Problem: Es sollten bei 1MHz Timer 1 CTC Werte zwischen 1000 und
2000 über den USART kommen. Es kommen aber nur Werte zwischen ca. 500
und 900. Wenn ich den Takt auf 100 kHz ändere, kommen Werte zwischen ca.
100 und 200 raus, was auch plausibel ist. (OCR1A = 16 -> 1 MHz / OCR1A =
160 -> 100 kHz). Aber warum? Ist das schon so zeitkritisch, dass der MC
nicht mehr nachkommt?
Gruß
Joachim
Hier noch ein anderer Ansatz:
https://www.mikrocontroller.net/attachment/highlight/284442
Das Dings liefert ein Vorwärts/Rückwärts Signal, PWM für einen Motor und
hat eine Failfunktion bei Ausfall des RC Signals - ist aber für einen
Tiny25-85.
Hallo,
F_CPU 16MHz?
Das hier ist deine Timerkonfiguration.
1
voidPPM_Counter_Timer1_init(void)
2
// Interrupt über CTC, ISR zählt mit 1 MHz
3
{
4
TCNT1=0;// Rücksetzen des Timers
5
OCR1A=16;// 1MHz
6
TCCR1B=(1<<WGM12);// CTC Modus
7
TCCR1B|=(1<<CS10);// Timer an / Kein Prescaler
8
TIMSK1=(1<<OCIE1A);// Timer/Counter1, Output Compare A Match Interrupt Enable
9
}
1
ISR(TIMER1_COMPA_vect)
2
// Interrupt 1 MHz, läuft
3
{
4
micros++;
5
}
Wie kommst du darauf das Timer 1 mit 1MHz läuft?
Laut meiner Rechnung läuft er mit 470,6kHz.
Nimm nochmal das Manual und die Formel vom CTC Mode zur Hand.
Eine andere Möglichkeit wäre der Input Capture Modus. Wäre auch genauer.
Joachim J schrieb:> Idee: 16 bit Variable über Timer mit 1 MHz zählen lassen.
Ich würde nicht gefühlte 70% der Rechenleistung mit dem schnellen
Hochzählen einer Variablen vergeuden. Denn immerhin hast du bei 16MHz
nur 16 Zyklen zwischen den Interrupts und davon gehen schon einige für
das Interrupt-Framework drauf. Dazu noch das eigentliche Hochzählen und
schon ist die Rechenzeit verbraucht.
Veit D. schrieb:> Eine andere Möglichkeit wäre der Input Capture Modus. Wäre auch genauer.
Oder einfach den 16-Bit-Zähler mit einem halbwegs geeigneten Vorteiler
geradeaus durchlaufen lassen und dann per Pin-Flankeninterrupt den
Anfangs- und Ende-Zeitstempel erfassen und die Differenz davon nehmen.
> Laut meiner Rechnung läuft er mit 470,6kHz.
Es ist immer gut, wenn man sich zur Kontrolle in so einen Timerinterrupt
mal einen Portpin togglet und den mit dem Oszi misst. Dann kann man
kontrollieren, ob der 1. überhaupt angesprungen wird und 2. das mit der
Häufigkeit tut wie man sich das gedacht hat.
EDIT: weil der vorgehende Post eine Beleidigung enthielt, wurde er
gelöscht. Die Information darin war allerdings erhaltenswert und lautete
zusammengefasst:
Erklehr Behr schrieb im Beitrag #6818605:
> die Anweisungen zum Posten von Sourcecode ... befolgen.>>> Wichtige Regeln - erst lesen, dann posten!>>> Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
Joachim J schrieb:> Idee: 16 bit Variable über Timer mit 1 MHz zählen lassen. Bei steigender> Flanke (Erkennung über INT0) Variable löschen und bei fallender Flanke> der Hauptschleife sagen, dass der Wert jetzt weiter verarbeitet werden> kann.
Viel zu kompliziert und laufzeitabhängig (Jitter).
Man läßt den Timer durchlaufen und nimmt den Input-Capture-Eingang.
Bei der einen Flanke den Capturewert merken und die Flanke umschalten.
Bei der anderen Flanke Differenz zum ersten Wert bilden und ausgeben.
Und bedenke: Eine Funkstrecke kann immer gestört sein! D.h. du kannst
auch mal einen Puls haben, der weit ab vom 1...2 ms-Fenster ist auch mal
0 oder 20 ms lang ist.
Darum nie auf ein einzelnes Sample verlassen, sondern immer eine
Plausibilitätskontrolle machen und/oder mitteln.
l. w. schrieb:>> ich möchte gerne die HIGH Pulslänge eines Modellbau Servo Signals messenPeter D. schrieb:> Viel zu kompliziert und laufzeitabhängig> Man läßt den Timer durchlaufen und nimmt den Input-Capture-Eingang.
Dieser Aussage von Peter stimme ich zu.
Allerdings folgendes:
Bei Modellbauservo ist wohl die PWM Periodendauer auf 20 ms definiert.
Ist die garantiert genau, so reicht die Messung des Hi Anteils.
Jedoch mag es Ansteuerungen geben, bei denen die 20 ms nicht exakt sind,
sei es durch Tolenanzen, ungenauen Oszillator o.ä.
Dann wäre die echte Berechnung des Duty Cycle sinnvoll.
Also nicht nur Hi Anteil messen (mit "input capture") sondern zusätzlich
auch gesamte Periode, dann Verältnisbildung (Division).
Der prinzipielle Vorgang ist dann derselbem welcher für den "sensiblen"
Temperatursensor SMT160 (SMT160-30) oder SMT172 verwendet wird.
https://forum.arduino.cc/t/smartec-smt172-temperature-sensor-library/359391/2
Dort bei "Jan. '16" #3 von EdwinCroissant :
= Capture the first falling edge and store the value of the timer in
startTime
= Capture the rising edge and store the value of the timer in tempTime
= Capture the second falling edge and add the difference between the
value of the timer and the tempTime to highTime
= Repeat until we have a multiple of 8 cycles from the sensor.
= On the last falling edge add the difference between the value of the
timer and the tempTime to the highTime and store the value of the timer
as endTime.
= Duty cycle is now the highTime divided by the difference between the
endTime and the startTime.
Erich schrieb:> Bei Modellbauservo ist wohl die PWM Periodendauer auf 20 ms definiert.> Ist die garantiert genau, so reicht die Messung des Hi Anteils.
Darauf kann man sich nicht verlassen. Meine alte Graupner FM4014 macht
z.B. 22ms und die Robbe Terra liegt bei 19ms.
Gemeinsam ist allen die immer exakte Pulslänge nach dem Dekoder (im
Receiver) von 1000µs bis 2000µs. Nur die zählt und muss plausibel sein.
Auch auf die Mittelstellung bei 1500µs kann man sich grob verlassen.
Meine Software von oben misst 50 Pulse auf Plausibilität und gibt dann
erst die Steuerung frei. D.h., es muss eine Sekunde lang ein plausibles
Signal kommen, ehe es losgeht. Fällt das Signal für einen Puls aus,
schaltet sie in den Notbetrieb.
Erich schrieb:> Bei Modellbauservo ist wohl die PWM Periodendauer auf 20 ms definiert.
Nö, die 20ms sind nur ein Richtwert. Werden mehrere Kanäle
hintereinander übertragen, darf sie auch länger dauern. Eine lange Pause
zwischen 2 Kanälen dient zur Erkennung, wann wieder Kanal 1 gesendet
wird. Die Information über den Servowert trägt nur die Impulsdauer.
Viele Servos unterstützen Periodendauern von weit weniger als 20ms, um
die Reaktionszeit (in Kombination mit einer passenden Ansteuerung) zu
reduzieren.
Hallo zusammen,
danke für die vielen Infos und Antworten! Das nächste mal kommt der Code
als Anhang. :-)
Ich stimme euch da zu, dass es besser ist, dass Signal über Input
Capture zu verwenden. Da ich allerdings 20 MHz habe und ich über die
Prescaler nicht auf glatte 1 MHz komme und im Nachgang umrechnen muss,
habe ich diesen Ansatz gewählt.
Ich kann die 470,6 kHz nachvollziehen, aber soweit ich das im Datenblatt
sehe, sollten die nur für den CTC im Waveform Modus gelten. Ich habe
mich hieran orientiert:
"An interrupt can be generated at each time the counter value reaches
the TOP value by either using the OCF1A or ICF1 flag according to the
register used to define the TOP value." (S. 101 ganz oben, aktuelles DB
vom 328p)
Und das wollte / will ich auch mit dem Code erreichen.
Mit meinem einfachen Oszi sehe ich auch, dass der Timer passt. Das
überprüfe ich später aber nochmal.
Rechnerisch passt die Formel für 20 MHz und 200 für OCR1A nicht (49,75
kHz Interrupt). Da müssten dann Werte für die Servoposition zwischen 49
und 99 herauskommen. Es kommen aber plausible Werte zwischen 100 und 200
heraus.
Zeiten zwischen Signalen mittels einem 1 MHz Zähler zu messen, scheinen
in der Arduino Bibliothek gängige Praxis zu sein und scheint dort auch
zu funktionieren (Funktion micros()). Deswegen wundert mich auch, dass
das hier nicht funktioniert.
Gruß
Joachim
Joachim schrieb:> Da ich allerdings 20 MHz habe und ich über die> Prescaler nicht auf glatte 1 MHz komme und im Nachgang umrechnen muss
Das ist gängige Praxis. Intern zählt man in Ticks und rechnet erst zum
Schluß für den Menschen um. So kann man auch mit einem 32.768kHz
Uhrenquarz auf 1/100s anzeigen.
Joachim schrieb:> Zeiten zwischen Signalen mittels einem 1 MHz Zähler zu messen, scheinen> in der Arduino Bibliothek gängige Praxis zu sein und scheint dort auch> zu funktionieren (Funktion micros()).
Dann lies Dir mal die Beschreibung dazu durch.
Einen Wert in µs auszugeben, heißt noch lange nicht, daß die Auflösung
1µs ist.
Joachim schrieb:> Da ich allerdings 20 MHz habe und ich über die> Prescaler nicht auf glatte 1 MHz komme und im Nachgang umrechnen muss,> habe ich diesen Ansatz gewählt.
Es juckt doch gar nichts, wenn du nicht auf eine "glatte" Zahl kommst.
Denn das, was du für eine "glatte" Zahl hältst, ist für den µC (der kann
super toll in Zweierpotenzen rechnen) eine höchst umständliche Zahl.
Und jetzt kommts: du musst diese für dich "glatte" Rechnung nur 1x
während der Entwicklungszeit machen. Der µC muss die für ihn
resultierende umständliche Rechnung andauernd den Rest des Lebens
machen.
Ergo ist es am sinnvollsten, du strengst 1x den Kopf an und denkst dir
eine Lösung aus, die der µC möglichst einfach ausführen kann. Dann ist
auch noch Platz und Zeit für weitere Aufgaben...
Erich schrieb:> Dann wäre die echte Berechnung des Duty Cycle sinnvoll.
Dieser Wert ist bei Modellbauservos im Grunde nutzlos und enthält keine
zuverlässige Information.
> Jedoch mag es Ansteuerungen geben, bei denen die 20 ms nicht exakt sind,> sei es durch Tolenanzen, ungenauen Oszillator o.ä.> Dann wäre die echte Berechnung des Duty Cycle sinnvoll.> Dort bei "Jan. '16" #3 von EdwinCroissant
Da geht es um einen schnarchlangsamen Temperatursensor. Da würde ich
ganz ohne Pinchangeinterrupt einfach in irgendeinem Timerinterrupt
jedesmal den Pin einlesen. Und mit 2 Zählern mitzählen, ob er gerade
high oder low ist. Aus diesen beiden Zählern kann ich dann das TV
ausrechnen:
DutyCycle = cntHi/(cntHi+cntLo)
Das wurde vor Kurzem im
Beitrag "Re: PWM Frequenzteiler in Hardware?" diskutiert und auch
im Beitrag "Re: Pulslänge mit STM32 Timer vermessen"
Hallo,
am Rande, wenn du den CTC Mode im Timer einstellst, dann gilt auch nur
die Formel vom CTC Mode.
Und wie die anderen schon geschrieben haben. Dich interessiert beim
Timer Zähler erstmal nur der reine Zählwert bzw. die Differenz zweier
Werte. Du weißt, weil du das ausgerechnet hast, wieviel Zeit ein Tick
entspricht. Das ist eine Konstante. Bei 20MHz immer Vielfache von 50ns.
Vorteil dabei es ist eine Ganzzahl. Erst am Ende rechnest du für eine
Ausgabe etc. deine Tick Differenz der Messung in eine Zeit um.
Wenn du Prescaler 8 verwendest reicht die Messauflösung noch locker aus.
Selbst Prescaler 64 sollte noch ausreichend sein. Rechne das alles in
Ruhe auf dem Papier durch.
Lothar M. schrieb:> Da geht es um einen schnarchlangsamen Temperatursensor.
Ach, wenn du meinst...
Der Temperaturwert (berechnet aus dem Duty Cycle) mag langsam sein,
nicht jedoch das PWM Signal selbst.
Lt. Datenblatt des SMT172 variiert die PWM Frequenz zwischen 0.5 und 7
kHz.
Nach meiner Berechnung ist das durchaus flotter als 20 ms.
Aber das ist eigentlich nur Nebenthema hier.
Ich wollte dem TO lediglich auf die verlinkte Library hinweisen, als
Beispiel für "input capture".
Gruss
Erich schrieb:> Nach meiner Berechnung ist das durchaus flotter als 20 ms.
Er meinte nicht die Signalfrequenz sondern die Geschwindigkeit mit der
sich die Temperatur verändert.
Man kann ein PWM Signal durchaus mit einer viel geringeren Frequenz
abtasten.
Ein Extremes Beispiel: Sagen wir mal das PWN Signal hätte 10 MHz. Wenn
du eine Stunde lang jede Sekunde das Signal digital abtastest und dabei
zählst wie oft du HIGH und wie oft du LOW gesehen hast, kommen dabei
vielleicht Zahlen wie diese heraus:
3200 mal LOW
400 mal HIGH
Dies ergibt ein Tastverhältnis von 400/3600 = 0,1111
So einfach kommst du auf einen mittleren Wert pro Stunde ohne dich
überhaupt mit den 10 Mhz herum schlagen zu müssen.
Genau so funktionieren Stichproben und representative Studien.
Stefan ⛄ F. schrieb:> Genau so funktionieren ... representative Studien.
Offtopic:
Ich weiß wie du das meinst. Muss dennoch meine Meinung dazu sagen.
Wenn man 1000 Leute fragt und auf 80 Millionen hochrechnet ist das genau
NICHT representativ wie immer behauptet. Das ist der Haken an den
Studien und Quotenermittlungen usw.
Stefan ⛄ F. schrieb:>> Er meinte nicht die Signalfrequenz sondern die Geschwindigkeit mit der> sich die Temperatur verändert.>
Ach wirklich?
>>>>Da würde ich ganz ohne Pinchangeinterrupt>>einfach in irgendeinem Timerinterrupt jedesmal den Pin einlesen.>>Und mit 2 Zählern mitzählen, ob er gerade high oder low ist.>>> Man kann ein PWM Signal durchaus mit einer viel geringeren Frequenz abtasten.>
Aber nicht,
wenn zur Erkennung der Signalgültigkeit genau 8 aufeinanderfolgende PWM
Zyklen betrachtet werden müssen.
(Steht im Datenblatt des "Schmach langsamen" Sensors).
> Genau so funktionieren Stichproben> und representative Studien.>
Die haben auch kein Datenblatt (Berechnungsvorschrift) und keine
Gültigkeitserkennung.
Ergebnis: 106% aller Deutschen können nicht prozentrechnen.
Gruss
Erich schrieb:> Ach, wenn du meinst...> Der Temperaturwert (berechnet aus dem Duty Cycle) mag langsam sein,> nicht jedoch das PWM Signal selbst.
Ja, aber wenn du das Verfahren verstanden hast, dann merkst du, dass die
Abtastung beliebig langsam sein darf. Und dann ist es eben völlig egal,
wie hochfrequent das PWM-Signal hat und ob diese Frequenz stabil ist.
Veit D. schrieb:> Wenn man 1000 Leute fragt und auf 80 Millionen hochrechnet ist das genau> NICHT representativ wie immer behauptet.
Das mit dem Kraut und den Rüben ist dir aber schon klar? Denn die
anderen, nicht berücksichtigten Signale haben ja keine "andere Meinung",
sondern jede einzelne Abtastung wird nur ein wenig mehr Genauigkeit
bringen. Und das ist dann pure Statistik und hat nichts mit Meinungen zu
tun.
Erich schrieb:> Aber nicht, wenn zur Erkennung der Signalgültigkeit genau> 8 aufeinanderfolgende PWM Zyklen betrachtet werden müssen.> (Steht im Datenblatt des "Schmach langsamen" Sensors).
Tja, dann darf man die Messdauer nicht beliebig lang machen, sondern
zählt einfach mit einem zusätzlichen Zähler ein Vielfaches dieser 8
Pulse ab (z.B. 4096) und wertet dann erst das Verhältnis aus.
Erich schrieb:> Ich wollte dem TO lediglich auf die verlinkte Library hinweisen, als> Beispiel für "input capture".
Richtig, er braucht aber nur einen Capture auf die steigende Flanke und
merkt sich t_rise und einen auf die fallende Flanke und merkt sich
t_fall. Dann ist die Pulsdauer im einfach tfall-trise, und falls
inzwischen ein Zählerüberlauf aufgetreten ist, wird der damit gratis
"rausgerechnet".
Lothar M. schrieb:> Veit D. schrieb:>> Wenn man 1000 Leute fragt und auf 80 Millionen hochrechnet ist das genau>> NICHT repräsentativ wie immer behauptet.> Das mit dem Kraut und den Rüben ist dir aber schon klar? Denn die> anderen, nicht berücksichtigten Signale haben ja keine "andere Meinung",> sondern jede einzelne Abtastung wird nur ein wenig mehr Genauigkeit> bringen. Und das ist dann pure Statistik und hat nichts mit Meinungen zu> tun.
Nein. Demnach müssten nur 1000 Leute zur Wahl gehen und repräsentieren
damit die Meinung aller Bundesbürger? Also wenn du das ernst meinst dann
gute Nacht.
Stefan ⛄ F. schrieb:> Man kann ein PWM Signal durchaus mit einer viel geringeren Frequenz> abtasten.>> Ein Extremes Beispiel: Sagen wir mal das PWN Signal hätte 10 MHz. Wenn> du eine Stunde lang jede Sekunde das Signal digital abtastest und dabei> zählst wie oft du HIGH und wie oft du LOW gesehen hast, kommen dabei> vielleicht Zahlen wie diese heraus:
Damit bekommst du das Tastverhältnis raus, aber nicht notwendigerweise
die Pulsbreite eines Servosteuersignals. Die Information ist (bis auf
einige Exoten) in der Dauer des High-Pulses codiert. Nur wenn die
Periodendauer konstant und bekannt ist, lässt sich die Information mit
deiner Methode statistisch bestimmen.
Wolfgang schrieb:> Damit bekommst du das Tastverhältnis raus, aber nicht notwendigerweise> die Pulsbreite eines Servosteuersignals.
Genau das war es, was
ich schrieb:> Erich schrieb:>> Dann wäre die echte Berechnung des Duty Cycle sinnvoll.> Dieser Wert ist bei Modellbauservos im Grunde nutzlosVeit D. schrieb:> Demnach müssten nur 1000 Leute zur Wahl gehen und repräsentieren> damit die Meinung aller Bundesbürger?
Was hast du denn dauernd mit deiner Wahl?
Du kannst die Unterabtastung eines PWM-Signals deshalb nicht mit einer
Wählerbefragung vergleichen, weil sich diese Meinung unter den
angenommenen 80Mio Leuten eben nicht ständig periodisch immer gleich
wiederholt(!), sondern völlig zufällig oder doch nicht zufällig verteilt
ist.
Genau das ist der Unterschied zwischen einem absolut unzufälligen
periodischen(!) PWM Signal und der Meinung zufällig verteilter Wähler.
Bei diskreten Sendern hat man oft eine Kette aus Monoflops verwendet.
Z.B. ein 74HC123 oder CD14538 mit 2 Potis konnte je 2 Kanäle kodieren.
Ein letzter Monoflop mit >10ms hat dann die lange Pause signalisiert.
Damit war die Periodendauer immer die Summe aller Kanäle + lange Pause,
d.h. überhaupt nicht konstant.
Wolfgang schrieb:> Damit bekommst du das Tastverhältnis raus, aber nicht notwendigerweise> die Pulsbreite eines Servosteuersignals.
Ja, bei einem Servo passt es nicht gut. Da müsste der Sender die Impulse
immer schön regelmäßig mit konstanter Periodendauer senden. Aber wer
will schon einen Empfänger bauen, der nur mit vielen (nicht mit allen)
Sendern funktioniert?
Ich bezog mich auf den Lösungsvorschlag für den "schnarch langsamen"
Temperatursensor. bei dessen Ausgangssignal interessiert man sich für
das Tastverhältnis.
Erich schrieb:> Ein erbärmliches, gleichwohl erwartetes Verhalten.
Was ist denn daran erbärmlich? Der Inhaber dieser Domain bestimmt, was
hier veröffentlicht wird und was er löschen will. Er hat hier nicht nur
das Hausrecht sondern sogar die Pflicht gewisse Beiträge aufzuräumen.
Was man mal positiv erwähnen sollte ist, dass hier unerwünschte Beiträge
nur noch äußerst selten sofort gelöscht werden. Die Diskussion wird
zugelassen wie sie sich ergibt. Gelöscht wird meistens erst ein paar
Tage später.
Ganz anders wäre es mit automatischen content filtern, die unsere
Regierung auf einigen Seiten nun doch erzwungen hat.
Lothar M. schrieb:
Naja Lothar, ursprünglich hast du auf meinen Kommentar reagiert. Dabei
ging es nur Offtopic um eine angebliche repräsentative Ermittlung. Das
hatte nichts mit wiederholter Unterabtastung zu tun. Irgenwelche
Umfragen kann man nur einmal machen. Das hast du schon richtig
geschrieben.
Der Rest ist mir schon zu sehr zerpflückt als das ich darauf sinnvoll
eingehen kann. Das wird nichts mehr. :-) Ich halte mich raus.
Erich schrieb:> Ein erbärmliches, gleichwohl erwartetes Verhalten.
Lass das Wort "Depp" weg und der Post bleibt stehen.
Wobei, wenn du das Wort aus dem Post löscht, dann bleibt ausser Gejammer
und einem unsinnigen Angriff auf mich nichts übrig. Und schon gar
nichts, was in der Sache irgendwie weiterhelfen würde.
> gleichwohl erwartetes Verhalten.
Es ist übrigens schon bedenklich, dass/wenn es mit den Löschungen immer
die selben trifft. Und die solche Löschungen schon "erwarten".
Veit D. schrieb:> Der Rest ist mir schon zu sehr zerpflückt
Richtig, da laufen 2 Threads in einem:
1. Highimpuls-Dauer-Messung
2. Bestimmung des Tastverhältnisses
> Ich halte mich raus.
Dürfte soweit wohl sowieso alles Nötige gesagt sein.
Hallo zusammen,
ich habe den Code auf Input Capture umgeschrieben und ich bekomme
saubere PP Werte. Den Code findet ihr im Anhang. Verbesserungsvorschläge
werden gerne angenommen. :-)
Auf einem ATMega 328p mit 16MHz und DRV8833 Motortreiber funktioniert
er. Allerdings "verhäddert" sich der Code auf einem Pololu Baby Orang
Utan (ATmega 328p mit 20 MHz und Toshiba TB6612FNG Motor Treiber).
Zwischendurch wir für das Motor Signal eine 0 berechnet, der Motor wird
kurzzeitig auf 0 gesetzt und stottert. Ich konnte noch nicht
herausfinden warum.
Gruß
Joachim
Joachim J schrieb:> Ich konnte noch nicht herausfinden warum.
Hast du mal überlegt, was passiert, wenn ein Störimpuls mit 100ns kommt,
einen Interrupt auslöst und dann, wenn du den Pegel am Interruptpin
einlesen willst, schon lange wieder "weg" ist?
Also sowas:
Joachim J schrieb:> Ich konnte noch nicht> herausfinden warum.
Du solltest testweise mal den seriellen Output in der Hauptschleife
rausnehmen. Das kostet immer wahnsinnig viel Zeit und oft weiss man bei
den Routinen nicht, was sie für Seiteneffekte haben.
Ich synchronisiere übrigens die Hauptschleife mit einem der Timer, damit
ich ein gleichmässiges Zeitraster habe.
Es lohnt sich auch, wie Lother schon sagte, die gemessene Zeit auf
Plausibilität zu prüfen, beovr man sie auf die Motoren loslässt.
Uner anderem deswegen habe ich so ausführliche Routinen für
Fehlererkennung in meinem Code (und weil ich das U-Boot nur ungerne
verliere).
Hallo zusammen,
ich hätte erwartet, dass es entweder gar nicht oder immer funktioniert:
Gleicher Code (bis auf Anpassungen zur Frequenz), gleicher MC Typ
(328p), unterschiedliche Taktfrequenz (16 MHz zu 20 MHz),
unterschiedlicher Motortreiber, aber gleicher Motor: Einmal funktioniert
es, einmal gar nicht. Und bei gar nicht auch erst dann, wenn der Motor
angeschlossen.
Bei einem U-Boot hätte ich natürlich auch mehr Sicherheit / eine
Plausibilitätsprüfung eingebaut. :-) Für meine Anwendung benötige ich
das nicht, da nichts wegfahren / wegschwimmen oder defekt gehen kann.
In dem 16 MHz Aufbau funktioniert alles wie gewünscht bzw. für meine
Anwendung ausreichend.
Gruß
Joachim