Forum: Mikrocontroller und Digitale Elektronik Pulsweite messen (Input Capture) mit ATMega328p


von Aa B. (aaab)


Angehängte Dateien:

Lesenswert?

Hallo,

Ich habe ein Programm geschrieben, womit man pulsweite des Squarewaves
am Input(ICP/PB0) in Millisekunden messen kann. Ich bin nicht so
zufrieden damit, irgendwas scheint immer noch nicht so optimal zu sein.
In diesem Beispiel, habe ich mit hilfe eines Switches (siehe Bild im
Anhang), den Steigende und Fallende Flanke emuliert und die Pulsweite
wird über dem USART ausgegeben. Meine Frage ist was mache ich hier immer
noch falsch oder wo kann ich noch optimieren?
Angehängt Source code.
1
#define SET   1
2
#define CLEAR 0
3
4
#define FOSC      16000000UL
5
#define baud_rate 9600
6
#define baud      FOSC/16/baud_rate-1
7
#define TICKS_VAL (FOSC/256)
8
#define LED_PIN(state)  { (state)?(PORTC |= (1<<PC0) ):(PORTC &= ~(1<<PC0)) ; }
9
#define TOGGLE_LED()    {PORTC ^= 1<<PC0; }
10
void capture_function();
11
12
volatile uint8_t button_flag=0;
13
volatile uint8_t capture_occured =0;
14
volatile uint8_t debounce_cnt=0;
15
volatile float temp=0;
16
volatile uint16_t ticks_t1=0;
17
volatile uint16_t ticks_t2=0;
18
volatile uint16_t elapsed_time=0;
19
20
int i=0;
21
22
23
volatile typedef enum edge_state_t{INIT_RISING,RISING,FALLING}edge_state;
24
25
26
volatile typedef struct {
27
  edge_state current_edge;
28
  edge_state next_edge;
29
  
30
}edge_t;
31
volatile edge_t edge;
32
33
 
34
unsigned char value_buf[5]={0};
35
36
void usart_init(unsigned int b_rate)
37
{
38
   UBRR0H=0x00;
39
   UBRR0L=0x00;
40
   UCSR0B=0x00;
41
   UCSR0C=0x00;
42
   UDR0  =0x00;
43
44
   UBRR0H  =(unsigned char)b_rate>>8;
45
   UBRR0L  =(unsigned char)b_rate;
46
47
   UCSR0B = ( (1<<RXEN0)  | (1<<TXEN0) );      // Polling mode: Wait till UDR is empty.
48
   UCSR0C = ( (1<<UCSZ00) | (1 << UCSZ01) );
49
}
50
51
void Transmit(unsigned char* c)
52
{
53
   while( !(UCSR0A & (1<<UDRE0)) );   
54
   UDR0=*c;
55
}
56
57
58
void init_input_capture()
59
{
60
  TIMSK1 = ( (1<<ICIE1) );                          /*Enable ICP Interrupt */
61
  TCCR1B = ( (1<<ICES1) | (1<<ICNC1) | (1<<CS12));  /*Enable rising edge detection, noise cancellaton, clock prescaler 256*/ 
62
  edge.current_edge = INIT_RISING;
63
  edge.next_edge = INIT_RISING;
64
  
65
  
66
}
67
void Transmit_string(char *str )
68
{
69
  for(i=0; i<strlen(str)+1;i++)
70
        Transmit(&str[i]);
71
        
72
        Transmit("\n");
73
  Transmit("\r");
74
      
75
  for(i=0; i<strlen(str)+1;i++)
76
   str[i]=0;
77
      
78
}
79
80
81
82
void capture_function()
83
{
84
  if(capture_occured==1)
85
  {
86
   LED_PIN(SET);
87
   
88
        } 
89
  else
90
    LED_PIN(CLEAR);
91
}  
92
93
void main()
94
{   
95
   DDRC  = 1<<PC0;  /*Pin PC0 os output LED */   
96
   PORTC = 0b00000001;  /*Enable PC0 internal pullup */   
97
  
98
   DDRB  = 0x00;   /*PB0 as INPUT*/
99
   PORTB=1<<PB0;
100
   
101
   usart_init(baud);
102
   
103
   init_input_capture();   
104
   sei();
105
   
106
   while(1)
107
   {
108
       //capture_function();
109
       
110
       if(edge.current_edge==FALLING)
111
       {         
112
      
113
       temp = (float)(ticks_t2 - ticks_t1)/(float)TICKS_VAL;
114
       temp *= 1000;
115
       elapsed_time = (uint16_t)temp;       
116
       sprintf(value_buf,"%1u", elapsed_time);
117
       Transmit_string(value_buf);       /*Transmit value in ms*/
118
    }       
119
    else
120
      TOGGLE_LED();
121
    
122
    }
123
    
124
     
125
}
126
127
ISR(TIMER1_CAPT_vect)
128
{      
129
      switch(edge.next_edge )
130
      {       
131
        case INIT_RISING:
132
        {             
133
       ticks_t1   = ICR1L;
134
       ticks_t1  |= (ICR1H <<8);
135
                         TCCR1B &=  ~(1<<ICES1);     /*Next Interrupt on Falling edge*/
136
                         edge.next_edge = FALLING;             
137
           
138
        }
139
        break;
140
       
141
        case RISING:
142
        {
143
            
144
            ticks_t1   = (uint16_t)ICR1L;
145
       ticks_t1  |= (uint16_t)(ICR1H <<8);
146
            TCCR1B &=  ~(1<<ICES1);   /*Next Interrupt on Falling edge*/
147
            edge.current_edge= RISING;
148
            edge.next_edge = FALLING;   
149
            
150
           
151
        }
152
        break;       
153
       
154
        case FALLING:
155
        {            
156
      ticks_t2   = (uint16_t)ICR1L;
157
      ticks_t2  |= (uint16_t)(ICR1H <<8);   
158
            TCCR1B    |=  (1<<ICES1);       /*Next Interrupt on Rising edge*/
159
            edge.current_edge = FALLING;        
160
            edge.next_edge = RISING;
161
        }
162
        break;       
163
       
164
        default:break;
165
     }
166
    
167
    
168
}

von Harald (Gast)


Lesenswert?

Kenne mich mit dem AT328 im Detail nicht aus, aber der hat doch auch den 
Capture für den 16-Bit Timer. Einfach im Interrupt den Capture-Wert 
auslesen und ggf. die Flanke wechseln (oder kann der gar beide 
Flanken?).

Wenn ich das richtig sehe, läuft in deinem Fall der Timer beim Auslesen 
weiter? Dabei kann es ja grobe Fehler geben, wenn der Zähler gerade 
einen Überlauf low/high Byte hat. Also der Zähler hat gerade 0x2FF, 
folgendes passiert:
- Du liest low=0xFF
- genau danach läuft der Zähler weiter von 0x2FF aus 0x300
- du liest das Highbyte high=0x03

Der sich ergebende Wert ist 0x3FF, also falsch.

von Aa B. (aaab)


Lesenswert?

Harald schrieb:
> Kenne mich mit dem AT328 im Detail nicht aus, aber der hat doch
> auch den
> Capture für den 16-Bit Timer. Einfach im Interrupt den Capture-Wert
> auslesen und ggf. die Flanke wechseln (oder kann der gar beide
> Flanken?).
Mache ich doch. :)
Beim nächsten mal wird der Interrupt durch steigende Flanke
1
 TCCR1B    |=  (1<<ICES1);
  verursacht
und beim fallende
1
 TCCR1B    &=  ~(1<<ICES1);
> Wenn ich das richtig sehe, läuft in deinem Fall der Timer beim Auslesen
> weiter? Dabei kann es ja grobe Fehler geben, wenn der Zähler gerade
> einen Überlauf low/high Byte hat. Also der Zähler hat gerade 0x2FF,
> folgendes passiert:
> - Du liest low=0xFF
> - genau danach läuft der Zähler weiter von 0x2FF aus 0x300
> - du liest das Highbyte high=0x03
>
> Der sich ergebende Wert ist 0x3FF, also falsch.

Okay, dass muss ich noch untersuchen.

von Harald (Gast)


Lesenswert?

Durch den Capture-Mechanismus gehst du genau diesen Problemen aus dem 
Weg. Das arme Silizium der Capture-Einheit soll doch auch ein schönes 
Leben haben und kein sinnloses Dasein fristen...

von Aa B. (aaab)


Lesenswert?

Harald schrieb:
> Durch den Capture-Mechanismus gehst du genau diesen Problemen aus
> dem
> Weg. Das arme Silizium der Capture-Einheit soll doch auch ein schönes
> Leben haben und kein sinnloses Dasein fristen...

Ich verstehe diese Aussage nicht wirklich. Da soll später ein andere 
Baustein kommen, ich wollte das überhaupt in betrieb nehmen und schauen 
ob "Time capture" wirklich passiert. Ich habe das am Anfang beschrieben 
oder?

von Dieter F. (Gast)


Lesenswert?

Aa B. schrieb:
> Ich bin nicht so
> zufrieden damit, irgendwas scheint immer noch nicht so optimal zu sein.

Kannst Du mal beschreiben, woran sich Deine Unzufriedenhet genau 
"festmacht"?
Was genau ist Dein Problem?

So etwas mit einem Taster zu testen ist nicht gerade ideal - Stichwort 
"Tastenprellung".

von Aa B. (aaab)


Lesenswert?

Dieter F. schrieb:

> Kannst Du mal beschreiben, woran sich Deine Unzufriedenhet genau
> "festmacht"?
> Was genau ist Dein Problem?
Wenn ich die taste ungefähr 1 Sekunde gedruckt halte und los lasse, 
hätte ich in der variable
1
elapsed_time
ca 1000 ms erwartet. Das klappt aber nicht immer. Es kommt manchmal 
100, 50 usw.


> So etwas mit einem Taster zu testen ist nicht gerade ideal - Stichwort
> "Tastenprellung".

Um debounce zu erkennen habe ich ein led togglen lassen, in diesem Fall 
ist der LED an wenn er steigende Flanke gesehen hat und noch keine 
fallende. Und dass passiert auch wie erwartet, also kein komische 
Rauschen oder so am pin.

 Ich hoffe es ist verständlich. :)

von Harald (Gast)


Lesenswert?

Das Register ICR1 macht genau das, was Du in deinem Source 
beabsichtigst. Er kopiert beim Ereignis den aktuellen Timerwert in ICR1 
- und zwar ohne die von mir benannten Probleme. Mittels ICES1 wählst du 
die Flanke, dieses Bit müsste dann im Capture(!) Interrupt umgeschaltet 
werden.
Also im Interrupt der pos Flanke Wert von ICR1 merken und im Interrupt 
der fallenden Flanke den aktuellen ICR1 vom gemerkten Wert abziehen.

Probleme gibt es weiterhin, wenn der Tastendruck länger ist als was der 
16-Bit zählen kann. Dann kann man per Software Überläufe zählen, aber 
die dann auftretenden Fallstricke sind noch einmal eine Liga höher.

von Peter D. (peda)


Lesenswert?

Aa B. schrieb:
> Wenn ich die taste ungefähr 1 Sekunde gedruckt halte und los lasse,
> hätte ich in der variableelapsed_time ca 1000 ms erwartet. Das klappt
> aber nicht immer. Es kommt manchmal
> 100, 50 usw.

Dann rechne mal nach.
Der Zählbereich ist nur 1,04s, d.h. bei "ungefähr" bist Du eben zu 
langsam.
Nimm den Prescaler 1024.

Man kann die Timer aber auch per SW leicht auf 32 Bit aufbohren.
Beitrag "AVR Timer mit 32 Bit"

von Toxic (Gast)


Angehängte Dateien:

Lesenswert?

Aa B. schrieb:
> Meine Frage ist was mache ich hier immer
> noch falsch oder wo kann ich noch optimieren?

Deinen Code habe ich mir nicht angesehen,aber hab'ne pdf 
zusammengestellt die das Thema Pulse Width behandelt.Ist zwar fuer 
Pics,laesst sich aber leicht auf andere uCs uebertragen - ist ja 
C-code.....
Das letztere Kapitel ist ein bischen Skizzenhaft(fuer 
Schueler/Studenten) dargestellt und sieht lausig aus,ist aber eine 
genauere Betrachtung wert.

von Aa B. (aaab)


Lesenswert?

Peter D. schrieb:

> Dann rechne mal nach.
> Der Zählbereich ist nur 1,04s, d.h. bei "ungefähr" bist Du eben zu
> langsam.
> Nimm den Prescaler 1024.
OMG! Ich kann nicht glauben das der "ATMega Chuck Norris" auf mein 
Beitrag geantwortet hat. Wie cool. Danke:)))
Du hast völlig recht, 1024 als prescaler, habe ich ausprobiert, 
unktioniert deutlich besser, einfach weil der timer tick kommt alle 
64us, damit kann ich bis ca. 4sec messen, aber da soll später ein US 
sensor kommen der ein Square wave erzeugt und dafür ist der Prescaler 
von 256 perfect.
> Man kann die Timer aber auch per SW leicht auf 32 Bit aufbohren.
> Beitrag "AVR Timer mit 32 Bit"

Vielen Dank, werde ich nachlesen. :)

: Bearbeitet durch User
von Dieter F. (Gast)


Lesenswert?

Aa B. schrieb:
> damit kann ich bis ca. 4sec messen, aber da soll später ein US
> sensor kommen der ein Square wave erzeugt und dafür ist der Prescaler
> von 256 perfect.

Na ja, wenn Du US messen willst - dann kann es ja nicht sooo weit sein. 
HC-SR04 misst bis ca. 3 m "genau"(~ 18 ms), beim SRF08 braucht ein 
Messzyklus ungefähr 64 ms. Vielleicht gibt es ja US-Module, die weiter 
(zuverlässig) messen - das wage ich aber leicht zu bezweifeln (vom 
Ballon Richtung Erde aus ggf. deutlich mehr).

Wenn Du größere Entfernungen messen möchtest ist US nicht unbedingt das 
Mittel erster Wahl. Bei den angepeilten 4 Sec. wären das ungefähr 660 m 
- das kannst Du vergessen ...

von m.n. (Gast)


Lesenswert?

Was Du genau messen willst ist mir nicht klar und auch nicht, ob man 
"Squarewaves" in Tüten kaufen kann.
Für Zeit/Impulsmessungen im Bereich 10 µs - 200 s kann man auch INT0 und 
INT1 verwenden: http://mino-elektronik.de/fmeter/fm_software.htm#bsp6
Es gibt auch eine Version für den Arduino Uno: 
Beitrag "Re: Stoppuhr – Geschwindigkeit – Pulsweite mit Atmega88"

von Aa B. (aaab)


Lesenswert?

Dieter F. schrieb:

> Na ja, wenn Du US messen willst - dann kann es ja nicht sooo weit sein.
> HC-SR04 misst bis ca. 3 m "genau"(~ 18 ms), beim SRF08 braucht ein
> Messzyklus ungefähr 64 ms. Vielleicht gibt es ja US-Module, die weiter
> (zuverlässig) messen - das wage ich aber leicht zu bezweifeln (vom
> Ballon Richtung Erde aus ggf. deutlich mehr).
Mir ist heute eingefallen dass man den TIMER2 laufen lassen kann, und 
diese Output on Compare (von Timer2) als input für mein ICP nutzen kann. 
erst heute morgen, manchmal bin ich zu doof. :)) Aber jetzt kann ich bis 
1 microsekunde messen.
Meinst Du US ist zu ungenau? Ic h habe diese PDF hier entdeckt, und habe 
mich darauf orientiert.

https://www.mikrocontroller.net/attachment/218122/HC-SR04_ultraschallmodul_beschreibung_3.pdf

> Wenn Du größere Entfernungen messen möchtest ist US nicht unbedingt das
> Mittel erster Wahl. Bei den angepeilten 4 Sec. wären das ungefähr 660 m
> - das kannst Du vergessen ...
Braucht man dafür nicht ein laser oder so? es sei denn, der Ultraschall 
Trigger Signal hat ein große Amplitude, oder verstehe ich falsch?

von Dieter F. (Gast)


Lesenswert?

Aa B. schrieb:
> Meinst Du US ist zu ungenau?

Kommt drauf an, was Du wie weit entfernt messen willst und welche 
Gegenstände ggf. im Schallkegel (15 Grad lt. Deinem PDF) sonst noch so 
sind. Ich habe damit nicht die besten Erfahrungen gemacht, was 
Genauigkeit angeht - aber das kann ein persönliches Problem sin :-\

Aa B. schrieb:
> Braucht man dafür nicht ein laser oder so?

Für größere Entfernungen - ja. Deswegen wunderte es mich auch, dass Du 
Dich so über die Messbereichserweiterung auf 4 Sek. gefreut hast :-)

von Peter D. (peda)


Lesenswert?

m.n. schrieb:
> Für Zeit/Impulsmessungen im Bereich 10 µs - 200 s kann man auch INT0 und
> INT1 verwenden:

Aber nur eingeschränkt. Sogar wenn keine anderen Interrupts erlaubt 
sind, ein Befehl kann 1..4 Zyklen dauern, d.h. man hat einen Jitter von 
3 Zyklen, ist also Faktor 3 ungenauer als der ICP.

von Äxl (geloescht) (Gast)


Lesenswert?

Der ICP ist dafür da, also nimm ihn! Machs doch gleich richtig ...

Äxl

von m.n. (Gast)


Lesenswert?

Peter D. schrieb:
> m.n. schrieb:
>> Für Zeit/Impulsmessungen im Bereich 10 µs - 200 s kann man auch INT0 und
>> INT1 verwenden:
>
> Aber nur eingeschränkt.

Keine Frage, aber bei längeren Zeiten fallen die Mikrosekunden kaum noch 
ins Gewicht.
Man erspart sich allerdings zusätzliche Logik, wenn man separate Signale 
für Start und Stopp hat (z.B. Lichstschranke), und man kann keine Flanke 
verlieren möchte (unabhängig vom gemessenen Ergebnis), wie es beim 
Umschalten von ICP passieren kann. Für die Flanken- und ggf. 
Kanalumschaltung muß die INT-Quelle ja kurz abgeschaltet und das Flag 
gelöscht werden.
Aber das sind dann Feinheiten.

Für ganz kurze Reflexionsmessungen könnte man einen TDC7200 
(Time-Digital-Converter) einsetzen. Aber bleiben wir beim AVR ;-)

von c-hater (Gast)


Lesenswert?

m.n. schrieb:

> Man erspart sich allerdings zusätzliche Logik, wenn man separate Signale
> für Start und Stopp hat (z.B. Lichstschranke)

"Zusätzliche Logik" = 2 Dioden und ein Widerstand...

> und man kann keine Flanke
> verlieren möchte (unabhängig vom gemessenen Ergebnis), wie es beim
> Umschalten von ICP passieren kann.

Erstmal: wenn man wirklich zwei Signale hat, braucht man überhaupt nicht 
umschalten, weil von jedem der beiden Signale nur jeweils eine Flanke 
relevant ist. Man wird natürlich dieselbe verwenden...

Davon abgesehen ist bei ICP die Chance, eine Flanke zu verlieren 
deutlich geringer als bei PCINT aus zwei Quellen.

von m.n. (Gast)


Lesenswert?

c-hater schrieb:
> "Zusätzliche Logik" = 2 Dioden und ein Widerstand...

Zu dieser "Schaltung" fehlt noch die Gurke => Gurkenschaltung.

> Erstmal: wenn man wirklich zwei Signale hat, braucht man überhaupt nicht
> umschalten, weil von jedem der beiden Signale nur jeweils eine Flanke
> relevant ist. Man wird natürlich dieselbe verwenden...

1. umzuschalten
2. die gleiche Flanke
3. am gleichen Eingang?

> Davon abgesehen ist bei ICP die Chance, eine Flanke zu verlieren
> deutlich geringer als bei PCINT aus zwei Quellen.

INT0/INT1 != PCINT

von c-hater (Gast)


Lesenswert?

m.n. schrieb:

> INT0/INT1 != PCINT

Da musst du dann aber auch wieder die Flanke umschalten. Und du hast 
zwei Interrupts, also hat jeder der beiden zusätzlich in seiner variable 
Latenz die Laufzeit des jeweils anderen...

Vergiss es! Nix ist besser zur Zeitmessung geeignet als ICP. Wenn die 
ICP-ISR die einzige im System ist, kann man mit entsprechend kompetenter 
Programmierung der ISR dafür sorgen, dass man GARANTIERT keine Flanke 
verpasst, die mehr als 10 Takte von der vorigen entfernt ist und man 
erfaßt jede dieser Flanken mit einer Genauigkeit von EINEM Takt. Das 
geht nur mit ICP, mit keiner anderen Methode ist das möglich, nicht mit 
PCINTx und auch nicht mit INTx, und schon garnicht, wenn auch noch zwei 
ISRs beschäftigt werden müssen...

Ok, natürlich hat auch ICP Grenzen. Die genannten 10 Takte kann man 
natürlich nicht dauerhaft erreichen, sondern nur so lange der Puffer im 
SRAM reicht, der die Events aufzeichnet. Zwischendurch müssen immer mal 
wieder "Pausen" im Eingangssignal sein, damit der Puffer auch 
ausgewertet und geleert werden kann., sonst läuft er irgendwann über und 
dann verliert man natürlich Flanken.

von Dieter F. (Gast)


Lesenswert?

c-hater schrieb:
> Vergiss es!

Ja, denk bitte mal an den gedachten Zweck. US-Module abfragen - meinst 
Du wirklich, da kommt es auf jede µs an? Oh, ich habe vergessen - bei 16 
MHz bewegen wir uns ja im Nanosekundenbereich - 1 ns = ~ 30 cm (Licht) 
:-)

von c-hater (Gast)


Lesenswert?

Dieter F. schrieb:

> Ja, denk bitte mal an den gedachten Zweck. US-Module abfragen - meinst
> Du wirklich, da kommt es auf jede µs an?

Was, zum Teufel, sind US-Module?

Abgesehen davon: Wenn man ein Feature in der Hardware hat, was 
nachweislich für einen bestimmten Zweck am besten geeignet ist, dann 
nutzt nur ein Vollidiot dieses Feature nicht. Das gilt selbst dann, wenn 
man die die erreichbare Leistung dieses Features für die Ziel-Anwendung 
garnicht benötigt.

Weil: Nicht benötigte Leistung kostet kein extra Geld, denn die Sache 
ist ja sowieso vorhanden und damit bereits bezahlt...

von Dieter F. (Gast)


Lesenswert?

c-hater schrieb:
> US-Module?

Nix Teufel - US = Ultraschall - darum geht es hier (falls es Dir 
entgangen ist). Außerdem habe ich nichts gegen ICP nur bei dem 
schnarchigen US-Modul mit der sowieso begrenzten Auflösung und 
Genauigkeit ist es wohl egal.

von m.n. (Gast)


Lesenswert?

c-hater schrieb:
>> INT0/INT1 != PCINT
>
> Da musst du dann aber auch wieder die Flanke umschalten.

Nein. Zu jedem INTx wird die aktive Flanke einmalig eingestellt und 
bleibt auch so.

> Nix ist besser zur Zeitmessung geeignet als ICP.

Auf jeden Fall, aber die AVR8 haben in der Regel nur ein 
Capture-Register, was die Umschalterei so oder so notwendig macht. Viel 
eleganter ginge es z.B. mit einem STM32Fxxx. Ein Griff in die Schaublade 
zeigt auch wie es geht: 
http://mino-elektronik.de/FM_407/fmeter_407.htm#a5
;-)

Aber der TO hat seinen ATmega328 und sollte sein Problem damit gelöst 
bekommen.

von Dieter F. (Gast)


Lesenswert?

c-hater schrieb:
> Das gilt selbst dann, wenn
> man die die erreichbare Leistung dieses Features für die Ziel-Anwendung
> garnicht benötigt.

Wenn ich mit viertel-Gas im 4. Gang mein Ziel genau so schnell wie mit 
Vollgas im 1. Gang erreiche, dann  fahre ich viertel-Gas - oder ich bin 
der angesprochene Vollidiot :-)

von Dieter F. (Gast)


Lesenswert?

m.n. schrieb:
> Auf jeden Fall, aber die AVR8 haben in der Regel nur ein
> Capture-Register, was die Umschalterei so oder so notwendig macht. Viel
> eleganter ginge es z.B. mit einem STM32Fxxx. Ein Griff in die Schaublade
> zeigt auch wie es geht:
> http://mino-elektronik.de/FM_407/fmeter_407.htm#a5
> ;-)

Schön - hindert Dich irgend jemand daran? Falls ja biete ich Dir meine 
Hilfe an.

von Aa B. (aaab)



Lesenswert?

Soooo, ein ganz kleine Update, ich habe die US Sensor mit ATMega328p in 
betrieb genommen, und er misst einfach, den Abstand zwischen US Sensor 
und dem Objekt in cm. Bisschen ungenau ist er schon und es gibt einiges 
zu optimieren, die ganze Operationen mit float im Program zum Beipiel. 
Display auf dem LCD. Kann man auch Temperature compensation einbauen, 
weil Geschwindigkeit von Sound wellen ändern sich mit Temperatur. aber 
da bräuchte ich ein vernünftige scheduler weil ich einige ISRs haben 
wurde.

Nächste schritt wäre auf dem STM32 zu portieren. :) Da hat man mehr 
Luxus, 32-bit Timer zum Capture, Output compare und FPU, und vieeeel 
mehr. :)

Verwendete sprache: nur C
Hardware: Arduino UNO
Toolchain: avr-gcc, avrdude(zum Programmieren)
OS: Linux

Danke euch für euer Tipps. :)

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.