Hallo Leute, bin neu hier und möchte mit dem AVR-Testboard MK2 (Atmega8) ne Volumenmessung testweise aufbauen. Um die Messung zu starten, müssen zwei Bedingungen erfüllt sein, sprich die zwei Taster müssen gedrückt sein (1-Signal). Außerdem werden die Ergebnisse über UART ausgegeben. Die Schleife sieht hier folgendermaßen aus. while (abfrage1 == 0) {;} while (abfrage2 == 0) {;} //auszuführende Anweisungen . . Hier wird doch nichts anderes gemacht als das bei einem anstehenden 0-Signal NICHTS gemacht wird oder? Jetzt habe ich teilweise das Problem, daß die Messung auch schon mal gestartet wird, wenn nur EIN Taster betätigt wird. Man sieht das daran, daß die Ergebnisse dann auch schon auf dem Bildschirm angezeigt werden. Kann das damit zusammenhängen, daß die Taster einfach prellen? Sonnige Grüße Daniel
du machst den vergleich ja auch nacheinander, aber die paar µC sollte dabei egal sein. Ich kann mir nicht vorstellen das das Problem vom prellen kommt. Wenn beide Taster an einem Port hängen kannst du es wiklich gleichzeitig vergleichen. Beispiel für bit0 und bit1 while ( (port & 0b00000011) != 0b00000011 ) {};
In Zeile 43 hast du einen typischen Fehler, den du korrigieren solltest. In deinem Schaltplan scheint es auch ein Problem bei IC1 zugeben.
Daniel Lo schrieb: > Um die Messung zu starten, müssen zwei Bedingungen erfüllt sein, sprich > die zwei Taster müssen gedrückt sein (1-Signal). Wenn die Startbedingung ist, daß beide Taster gleichzeitig gedrückt sein müssen, dann mußt Du die beiden auch in einer Schleife abfragen, nicht hintereinander. > while (abfrage1 == 0) {;} > while (abfrage2 == 0) {;} Dein Programm bleibt in der ersten Zeile so lange hängen, bis abfrage1 erfüllt ist, dann in der zweiten Zeile, bis abfrag2 erfüllt ist, egal welchen Zustand zu dem Zeitpunkt abfrage1 hat. Dadurch wird die Messung nicht nur beim gleichzeitigen Drücken beider Taster gestartet, sondern auch, wenn zuerst Taster 1 gedrückt und wieder losgelassen und dann Taster 2 gedrückt wird. Richtig wäre:
1 | while (abfrage1 == 0 || abfrage2 == 0); |
Diese Schleife wird solange wiederholt, bis beide Abfragen gleichzeitig
einen Wert ungleich 0 liefern. Die Geschweiften Klammern kannst Du
übrigens weglassen, wenn sie sowieso leer sind. Wie Peter schrieb,
lassen sich die beiden Tests zusammenfassen, wenn beide Taster am
gleichen Port hängen.
> Kann das damit zusammenhängen, daß die Taster einfach prellen?
Dein eigentliches Problem lag wie gesagt nicht am Prellen, aber eine
Entprellung kann zusätzlich noch nötig sein, insbesondere falls die Zeit
für eine Messung unterhalb der Prellzeit Deiner Tasten liegt.
Falls es, wie ich annehme, um Deinen ganzen Code herum eine
Endlosschleife gibt, solltest Du außerdem nach der Messung noch warten
bis die Tasten wieder losgelassen werden, sonst ist ja die
Startbedingung am Ende immer noch erfüllt und es wird sofort die nächste
Messung gestartet.
R. Max schrieb: > Richtig wäre: > while (abfrage1 == 0 || abfrage2 == 0); > Diese Schleife wird solange wiederholt, bis beide Abfragen gleichzeitig > einen Wert ungleich 0 liefern. Die Geschweiften Klammern kannst Du > übrigens weglassen, wenn sie sowieso leer sind. Wie Peter schrieb, > lassen sich die beiden Tests zusammenfassen, wenn beide Taster am > gleichen Port hängen. aber nur weil beide bedingungen in einer Zeile stehen werden sie immer noch nach einander verglichen. Das ist also nichts mit gleichzeitig. Von der Sache ist das auch nichts anderes als wie oben nur etwas üblicher/schöner geschrieben. Wird aber das Problem nicht lösen
So, habe festgestellt, daß die Messung schon gestartet wird, wenn nur Abfrage2 (in diesem Fall mess_ok) erfüllt ist, irgendwas läuft da schief, am Programm selbst kann das doch nicht liegen oder? Hier mal das komplette Programm, ist übrigens nicht von mir geschrieben. Ich bin nur dabei zu versuchen, es zu verstehen. Nochmal zum Verständnis: Es handelt sich um eine Volumenmessung, die folgendermaßen funktionieren soll. Es gibt ein Laufband und die Volumenmessung des Produktes wird durch eine Lichtschranke angestoßen, zusätzlich soll die Bedingung Band läuft (Variable Band_ok) erfüllt sein. An der Seite sind zwei Sensoren angeschlossen und über dem Band selbst nochmal ein Sensor. Diese messen dann das Volumen (simuliert durch Potentiometer). Die Länge wird über die Bandgeschwindigkeit und die Lichtschranke ermittelt. //---------------------------------------------------------------------- // Titel : C Grundgerüst für das myAVR-Board //---------------------------------------------------------------------- // Funktion : ... // Schaltung : ... //---------------------------------------------------------------------- // Prozessor : Atmega8... // Takt : 3.6864 MHz // Sprache : C // Datum : 8.03.2010... // Version : ... // Autor : ... //---------------------------------------------------------------------- #define F_CPU 3686400 // Taktferquenz des myAVR-Boards #include <avr\io.h> // AVR Register und Konstantendefinitionen #include <inttypes.h> //Interrupt- Typen #include <avr\interrupt.h> //Defs fuer Interrupts #define volgrenzw 400 //Volumengrenzert #define speed 5 //5 mm bei 10 ms //---------------------------------------------------------------------- // globale Variable //---------------------------------------------------------------------- int adc_wert = 0; //Variable fuer die ADC-Messung long volume = 0; //Var zur Berechnung des Volumens volatile int cnt_ms = 0; //Zähler für Zeitmessung (10ms) volatile int band_ok = 0; //Band läuft volatile int mess_ok = 0; //Messung aktiv (Gegenstand auf Band) int sensor_buffer = 0 ; // Messwertspeicher char ergebnis[7]; //5 Stellen + Kennungt + 0 für Ende //---------------------------------------------------------------------- ---- // Initialisiere Uart- Schnittstelle //---------------------------------------------------------------------- ---- void usartinit (void) { /* Das Frameformat Start, 8Datenbits u. 1 Stoppbit ist nach Reset bereits im USART eingestellt */ UBRRL = 23; //9600 Baud UCSRB =0x08; //Sender enable } //---------------------------------------------------------------------- ---- //---------------------------------------------------------------------- ---- // Gebe Zeichen über Uart aus //---------------------------------------------------------------------- ---- void usartputc(char data ) { while (!(UCSRA&32)); //warte bis usart leer UDR=data; //sende zeichen } //---------------------------------------------------------------------- ---- //---------------------------------------------------------------------- ---- // Ausgabe Buffer über Usart //---------------------------------------------------------------------- ---- void print(char buffer[]) //Ausgabe Zeichenpuffer { for (int i=0;buffer[i] != 0 ;i++ ) usartputc(buffer[i]); } //---------------------------------------------------------------------- ---- //---------------------------------------------------------------------- ---- // Umwandlung Int nach ASCII String //---------------------------------------------------------------------- ---- void int_to_string(int x,char s[],char ken) { int i ; //Index,lokale Variable for (i=0;i<6;i++ ) //Vorbesetzung mit Leerzeichen s[i]= ' '; s[i] = 0; //kennzeichne Ende String s[0] = ken; //Ausgabe Kennung i=5; //Umsetzung von bin nach dez do { s[i--] = x % 10 + '0'; //Modulus 10 der Rest nach ASCII } while (( x /= 10) > 0); //Wert ist Wert durch 10 } //---------------------------------------------------------------------- ---- //---------------------------------------------------------------------- ---- // Ausgabe CR und LF an das Terminal //---------------------------------------------------------------------- ---- void cr_lf() // Ausgabe CR und LF an das Terminal { usartputc(0x0d); //Ausgabe Wagenrücklaufzeichen usartputc(0x0a); //Ausgabe Zeilenwechselzeichen } //---------------------------------------------------------------------- ---- //---------------------------------------------------------------------- -- // Längenmessung über eine Laufzeitmessung (v=s/t) //---------------------------------------------------------------------- ISR (TIMER0_OVF_vect) { TCNT0 = (255-144) ; // Wert für 10 ms bei Vorteiler 256 if (band_ok && mess_ok) //Messung aktiv und gültig ++cnt_ms; } //---------------------------------------------------------------------- // ISR INT0: Band läuft; von externer Steuerung //---------------------------------------------------------------------- ISR (INT0_vect) { if (PIND & 0b00000100) //Abfrage PD2 (Pin 4)auf ein band_ok = 1; //Band läuft else band_ok = 0; //Band ist aus } //---------------------------------------------------------------------- // ISR INT1: In Messung; von Reflexionslichtschranke //---------------------------------------------------------------------- ISR (INT1_vect) { if (PIND & 0b00001000) //Abfrage PD3 (Pin 5)auf ein mess_ok = 1; //Objekt in Lichtschranke else mess_ok = 0; //Objekt ist nicht in Lichtschrank } //---------------------------------------------------------------------- // ADC Messung mit 10 Bit //---------------------------------------------------------------------- void adc_mess(void) { sbi(ADCSRA,6); //starte Messung while (ADCSRA & 0b01000000)//Messung fertig ? { ; } sbi (ADCSRA,4); //lösche ADIF Bit adc_wert = ADC; //lese Messwert adc_wert &= 0x3ff; //auf 10 Bit begrenzen } //---------------------------------------------------------------------- // Init- Funktion //---------------------------------------------------------------------- void init (void) { usartinit(); TCNT0 =(255-144); //Wert für 10ms bei Vort. 256 TCCR0 = 0x04 ; //Vorteiler 256 für Timer 0 TIMSK = 0x01 ; //Freigabe Interrupt Timer 0 //DDRC u. Dsind nach Reset //Eingänge PORTD |= 0b00001100; //Pul up auf Bit 2 u. 3 DDRB |= 0b00000011; //Bit 0 u. 1von Port B sind Ausgänge PORTB &= 0b11111100; //Port B Bit 0 u. 1 auf 0 GICR = 0b11000000; //Freigabe ext.INT0 u. 1 MCUCR = 0b00000101; //Interrupt auf jeder Flanke ADMUX = 0; //externe Ref., Mux auf Kanal 0 ADCSRA = 0b10010101; //ADC Einzelmessung,Vorteiler ./.32 } main () // Hauptprogramm, startet bei Power ON und Reset { int b=0,b1=0,b2=0,h=0,l=0; //interne Variable init () ; //Initialisierung sei () ; //Hauptfreigabe Interrupt for (;;) { while (band_ok == 0){;} //warte auf Band läuft while (mess_ok == 0){;} //warte auf Reflexionslichtschranke ADMUX = 0; //starte mit Sensor Breite 1 (ADMUX=0 --> PC0, siehe Pinbelegung ATmega8) adc_mess(); //Messung Breite 1 b1 = adc_wert; //Breite 1 sensor_buffer = b1; int_to_string(sensor_buffer,ergebnis,'L'); //Umwandlung Ergebnis von int nach ASCII string print(ergebnis); //Ausgabe Ergebnis cr_lf() ; //Ausgabe CR und LF an das Terminal ADMUX = 1; //starte mit Sensor Breite 2 (ADMUX=1 --> PC1, siehe Pinbelegung ATmega8) adc_mess(); //Messung Breite 2 b2 = adc_wert; //Breite 2 sensor_buffer = b2; int_to_string(sensor_buffer,ergebnis,'R'); //Umwandlung Ergebnis von int nach ASCII string print(ergebnis); //Ausgabe Ergebnis cr_lf() ; //Ausgabe CR und LF an das Terminal ADMUX = 2; //starte mit Sensor Höhe (ADMUX=2 --> PC2, siehe Pinbelegung ATmega8) adc_mess(); //Messung Höhe h = adc_wert; //Höhe sensor_buffer = h; int_to_string(sensor_buffer,ergebnis,'H'); //Umwandlung Ergebnis von int nach ASCII string print(ergebnis); //Ausgabe Ergebnis cr_lf() ; //Ausgabe CR und LF an das Terminal while (mess_ok == 1){;} //warte auf Ende Längenmessung l = cnt_ms ; //Zeit in 10 ms TICS l *= speed ; //Länge in mm if (l<=0){l=1;} //Mindestlänge 1mm cnt_ms = 0; //neu stellen b = 1200 - (b1 + b2); //Näherungswert für Breite in mm h = 2500 -(h*244/100); //Berechne Höhe in mm if (h < 0){h = 1;} //nicht negativ if (h>2000) {h=2000;} //nicht höher als 2000mm b = 200; //Test h = 1000; //Test l = 1999; //Test vol < 400 // l = 2000; //Test für vol >=400 volume = (long)b; //Breite volume = volume *(long)h; //Breite * Höhe volume = volume * (long)l; //Volumen volume = volume /1000000; //Umrechnung in dm³ if (volume < volgrenzw) { PORTB &= 0b11111101; // Volumen groß aus PORTB |= 0b00000001; // Volumen klein ein (PB0) } else { PORTB &= 0b11111110; // Volumen klein aus PORTB |= 0b00000010; // Volumen groß ein (PB1) } } } //----------------------------------------------------------------------
Peter schrieb: > aber nur weil beide bedingungen in einer Zeile stehen werden sie immer > noch nach einander verglichen. Der Punkt ist nicht, daß die Bedingungen in einer Zeile stehen, sondern daß sie in einer Schleife stehen. Meine Variante "merkt" sich nicht, daß Taste 1 schonmal gedrückt wurde und läßt sich dann alleine mit Taste 2 starten. Die paar Taktzyklen, die zwischen den beiden Vergleichen vergehen, sind für manuell betätigte Taster vernachlässigbar.
Daniel Lo schrieb: > Es gibt ein Laufband und die Volumenmessung des Produktes wird durch eine > Lichtschranke angestoßen, zusätzlich soll die Bedingung Band läuft (Variable > Band_ok) erfüllt sein. Dann mach es so, wie ich geschrieben habe. Dein Code stellt derzeit nur sicher, daß das Band zu Beginn des Hauptschleifendurchlaufs läuft, aber er merkt nicht, wenn es vor dem Ansprechen der Lichtschranke wieder abgeschaltet wird.
Daniel Lo schrieb: > Hallo Leute, > bin neu hier und möchte mit dem AVR-Testboard MK2 (Atmega8) ne > Volumenmessung testweise aufbauen. > Um die Messung zu starten, müssen zwei Bedingungen erfüllt sein, sprich > die zwei Taster müssen gedrückt sein (1-Signal). > Außerdem werden die Ergebnisse über UART ausgegeben. > Die Schleife sieht hier folgendermaßen aus. > while (abfrage1 == 0) {;} > while (abfrage2 == 0) {;} > //auszuführende Anweisungen > . > . > > Hier wird doch nichts anderes gemacht als das bei einem anstehenden > 0-Signal NICHTS gemacht wird oder? Ja. > Jetzt habe ich teilweise das Problem, daß die Messung auch schon mal > gestartet wird, wenn nur EIN Taster betätigt wird. Nachdem du vorher den anderen einzeln betätigt hast? Du wartest nämlich zuerst, bis abfrage1 ungleich 0 ist, ohne dich dabei für abfrage2 zu interessieren. Sobald das eingetreten ist, springst du zur zweiten Warteschleife und wartest dort nun, bis abfrage2 ungleich 0 ist, unabhängig davon, wie inzwischen der Wert von abfrage1 ist.
Danke, das war ein wichtiger Hinweis. Wenn ich das ganze zum ersten Mal ablaufen lasse, dann muß ich tatsächlich zuerst Taste 1 drücken. Werde das mit der vorgeschlagenen Schleife direkt mal ausprobieren. Mal was anderes. Als Messergebnisse werden ja momentan die Werte von Sensor Links ('L'), Sensor Rechts ('R') und Sensor oben ('H') ausgegeben. Jetzt habe ich zusätzlich mal die Länge anzeigen wollen, was auch scheinbar klappt. Nur egal wie lange ich die Taste gedrückt halte, es kommen immer andere (sprich unplausible) Ergebnisse heraus, woran kann das liegen? Könnte es in diesem Fall an evtl. prellenden Tastern liegen? Hier nochmal das geänderte Programm, habe die neu eingefügten Zeilen vorne mit einem Pfeil (-->) gekennzeichnet, damit man die Änderungen leichter sieht. //---------------------------------------------------------------------- // Titel : C Grundgerüst für das myAVR-Board //---------------------------------------------------------------------- // Funktion : ... // Schaltung : ... //---------------------------------------------------------------------- // Prozessor : Atmega8... // Takt : 3.6864 MHz // Sprache : C // Datum : 8.03.2010... // Version : ... // Autor : ... //---------------------------------------------------------------------- #define F_CPU 3686400 // Taktferquenz des myAVR-Boards #include <avr\io.h> // AVR Register und Konstantendefinitionen #include <inttypes.h> //Interrupt- Typen #include <avr\interrupt.h> //Defs fuer Interrupts // #include <stdio.h> #define volgrenzw 400 //Volumengrenzert #define speed 5 //5 mm bei 10 ms //---------------------------------------------------------------------- // globale Variable //---------------------------------------------------------------------- int adc_wert = 0; //Variable fuer die ADC-Messung long volume = 0; //Var zur Berechnung des Volumens volatile int cnt_ms = 0; //Zähler für Zeitmessung (10ms) volatile int band_ok = 0; //Band läuft volatile int mess_ok = 0; //Messung aktiv (Gegenstand auf Band) int sensor_buffer = 0 ; // Messwertspeicher char ergebnis[7]; //5 Stellen + Kennungt + 0 für Ende //---------------------------------------------------------------------- ---- // Initialisiere Uart- Schnittstelle //---------------------------------------------------------------------- ---- void usartinit (void) { /* Das Frameformat Start, 8Datenbits u. 1 Stoppbit ist nach Reset bereits im USART eingestellt */ UBRRL = 23; //9600 Baud UCSRB =0x08; //Sender enable } //---------------------------------------------------------------------- ---- //---------------------------------------------------------------------- ---- // Gebe Zeichen über Uart aus //---------------------------------------------------------------------- ---- void usartputc(char data ) { while (!(UCSRA&32)); //warte bis usart leer UDR=data; //sende zeichen } //---------------------------------------------------------------------- ---- //---------------------------------------------------------------------- ---- // Ausgabe Buffer über Usart //---------------------------------------------------------------------- ---- void print(char buffer[]) //Ausgabe Zeichenpuffer { for (int i=0;buffer[i] != 0 ;i++ ) usartputc(buffer[i]); } //---------------------------------------------------------------------- ---- //---------------------------------------------------------------------- ---- // Umwandlung Int nach ASCII String //---------------------------------------------------------------------- ---- void int_to_string(int x,char s[],char ken) { int i ; //Index,lokale Variable for (i=0;i<6;i++ ) //Vorbesetzung mit Leerzeichen s[i]= ' '; s[i] = 0; //kennzeichne Ende String s[0] = ken; //Ausgabe Kennung i=5; //Umsetzung von bin nach dez do { s[i--] = x % 10 + '0'; //Modulus 10 der Rest nach ASCII } while (( x /= 10) > 0); //Wert ist Wert durch 10 } //---------------------------------------------------------------------- ----- void laenge() //Ausgabe Wort Länge { usartputc(0x4c); //L usartputc(0x61); //a usartputc(0x65); //e usartputc(0x6e); //n usartputc(0x67); //g usartputc(0x65); //e usartputc(0x0d); //Wagenrücklauf usartputc(0x0a); //Zeilenwechsel } //---------------------------------------------------------------------- ---- //---------------------------------------------------------------------- ---- // Ausgabe CR und LF an das Terminal //---------------------------------------------------------------------- ---- void cr_lf() // Ausgabe CR und LF an das Terminal { usartputc(0x0d); //Ausgabe Wagenrücklaufzeichen usartputc(0x0a); //Ausgabe Zeilenwechselzeichen } //---------------------------------------------------------------------- ---- //---------------------------------------------------------------------- -- // Längenmessung über eine Laufzeitmessung (v=s/t) //---------------------------------------------------------------------- ISR (TIMER0_OVF_vect) { TCNT0 = (255-144) ; // Wert für 10 ms bei Vorteiler 256 if (band_ok && mess_ok) //Messung aktiv und gültig ++cnt_ms; } //---------------------------------------------------------------------- // ISR INT0: Band läuft; von externer Steuerung //---------------------------------------------------------------------- ISR (INT0_vect) { if (PIND & 0b00000100) //Abfrage PD2 (Pin 4)auf ein band_ok = 1; //Band läuft else band_ok = 0; //Band ist aus } //---------------------------------------------------------------------- // ISR INT1: In Messung; von Reflexionslichtschranke //---------------------------------------------------------------------- ISR (INT1_vect) { if (PIND & 0b00001000) //Abfrage PD3 (Pin 5)auf ein mess_ok = 1; //Objekt in Lichtschranke else mess_ok = 0; //Objekt ist nicht in Lichtschrank } //---------------------------------------------------------------------- // ADC Messung mit 10 Bit //---------------------------------------------------------------------- void adc_mess(void) { sbi(ADCSRA,6); //starte Messung while (ADCSRA & 0b01000000)//Messung fertig ? { ; } sbi (ADCSRA,4); //lösche ADIF Bit adc_wert = ADC; //lese Messwert adc_wert &= 0x3ff; //auf 10 Bit begrenzen } //---------------------------------------------------------------------- // Init- Funktion //---------------------------------------------------------------------- void init (void) { usartinit(); TCNT0 =(255-144); //Wert für 10ms bei Vort. 256 TCCR0 = 0x04 ; //Vorteiler 256 für Timer 0 TIMSK = 0x01 ; //Freigabe Interrupt Timer 0 //DDRC u. Dsind nach Reset //Eingänge PORTD |= 0b00001100; //Pul up auf Bit 2 u. 3 DDRB |= 0b00000011; //Bit 0 u. 1von Port B sind Ausgänge PORTB &= 0b11111100; //Port B Bit 0 u. 1 auf 0 GICR = 0b11000000; //Freigabe ext.INT0 u. 1 MCUCR = 0b00000101; //Interrupt auf jeder Flanke ADMUX = 0; //externe Ref., Mux auf Kanal 0 ADCSRA = 0b10010101; //ADC Einzelmessung,Vorteiler ./.32 } main () // Hauptprogramm, startet bei Power ON und Reset { int b=0,b1=0,b2=0,h=0,l=0,lae=0; //interne Variable init () ; //Initialisierung sei () ; //Hauptfreigabe Interrupt for (;;) { while (band_ok == 0){;} //warte auf Band läuft while (mess_ok == 0){;} //warte auf Reflexionslichtschranke cr_lf(); ADMUX = 0; //starte mit Sensor Breite 1 (ADMUX=0 --> PC0, siehe Pinbelegung ATmega8) adc_mess(); //Messung Breite 1 b1 = adc_wert; //Breite 1 sensor_buffer = b1; int_to_string(sensor_buffer,ergebnis,'L'); //Umwandlung Ergebnis von int nach ASCII string print(ergebnis); //Ausgabe Ergebnis cr_lf() ; //Ausgabe CR und LF an das Terminal ADMUX = 1; //starte mit Sensor Breite 2 (ADMUX=1 --> PC1, siehe Pinbelegung ATmega8) adc_mess(); //Messung Breite 2 b2 = adc_wert; //Breite 2 sensor_buffer = b2; int_to_string(sensor_buffer,ergebnis,'R'); //Umwandlung Ergebnis von int nach ASCII string print(ergebnis); //Ausgabe Ergebnis cr_lf() ; //Ausgabe CR und LF an das Terminal ADMUX = 2; //starte mit Sensor Höhe (ADMUX=2 --> PC2, siehe Pinbelegung ATmega8) adc_mess(); //Messung Höhe h = adc_wert; //Höhe sensor_buffer = h; int_to_string(sensor_buffer,ergebnis,'H'); //Umwandlung Ergebnis von int nach ASCII string print(ergebnis); //Ausgabe Ergebnis cr_lf() ; //Ausgabe CR und LF an das Terminal while (mess_ok == 1){;} //warte auf Ende Längenmessung l = cnt_ms ; //Zeit in 10 ms TICS l *= speed ; //Länge in mm if (l<=0){l=1;} //Mindestlänge 1mm // lae = l; //Länge (l) wird der Variable lae zugeordnet // lae = 2000; --> int_to_string(l,ergebnis,'Z'); //Umwandlung Ergebnis von int //nach ASCII string --> laenge(); --> print(ergebnis); //Ausgabe Ergebnis --> cr_lf(); //neue Zeile cnt_ms = 0; //neu stellen b = 1200 -(b1 + b2); //Näherungswert für Breite in mm h = 2500 -(h*244/100); //Berechne Höhe in mm if (h < 0){h = 1;} //nicht negativ if (h>2000) {h=2000;} //nicht höher als 2000mm // b = 200; //Test // h = 1000; //Test // l = 1999; //Test vol <400 // l = 2000; //Test für vol >=400 volume = (long)b; //Breite volume = volume *(long)h; //Breite * Höhe volume = volume * (long)l; //Volumen volume = volume /1000000; //Umrechnung in dm³ if (volume < volgrenzw) { PORTB &= 0b11111101; // Volumen groß aus PORTB |= 0b00000001; // Volumen klein ein (PB0) } else { PORTB &= 0b11111110; // Volumen klein aus PORTB |= 0b00000010; // Volumen groß ein (PB1) } } } //----------------------------------------------------------------------
Kann mir vielleicht auch nochmal jemand die Funktion int_to_string erklären? Hänge da ein wenig, was das Verständnis angeht. Versuche das mal mit meinen eigenen Worten zu beschreiben soweit möglich. Also: Zuerst wird eine Integer-Variable i erzeugt, danach in einer for-Schleife auf 0 gesetzt. Ist nun i kleiner 6, so wird i mit jedem Durchlauf um 1 erhöht. Danach hört's bei mir leider schon auf.
R. Max schrieb: > Richtig wäre: > while (abfrage1 == 0 || abfrage2 == 0); Nö. Versuch statt || (ODER) mal && (UND) ...
Ist doch eigentlich gut kommentiert. i wird als Arrayindex genommen. Mit i = 5 wird auf das letzte "echte" Zeichen im Array zugegriffen und der Wert mit dem Trick (+ '0') in ASCII umgewandelt. Im ASCII-Code liegen alle Zeichen schön sortiert hintereinander; schau dir mal die Tabelle irgendwo an. Mit + '0' wird daher ein konstanter Abstand vom Start der Tabelle hergestellt. Steht in so jedem C-Buch drin.
Lutz schrieb: > R. Max schrieb: >> Richtig wäre: >> while (abfrage1 == 0 || abfrage2 == 0); > > Nö. Versuch statt || (ODER) mal && (UND) ... Das ODER stimmt schon, denn die beiden Terme liefern 1, solange die jweilige Taste nicht gedrückt ist und die Schleife soll erst verlassen werden, wenn beide Tasten gedrückt sind, nicht schon bei einer.
Daniel Lo schrieb: > Versuche das mal mit meinen eigenen Worten zu beschreiben soweit > möglich. > Also: > Zuerst wird eine Integer-Variable i erzeugt, danach in einer > for-Schleife auf 0 gesetzt. Ist nun i kleiner 6, so wird i mit jedem > Durchlauf um 1 erhöht. > Danach hört's bei mir leider schon auf. Du erklärst das nicht mit eigenen Worten. Du liest nur vor. Das hat mit erklären nichts zu tun. Punkt 1 ******* Du brauchst Wissen, wie Stringverarbeitung in C funktioniert http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F Punkt 2 ******* Was ergibt 38 dividiert durch 10 38 / 10 -> 3 Und was ist der Rest bei dieser Division? (% ist die Modulo-Opertion und sie liefert den Rest einer Division) 38 % 10 -> 8 Hmm, 38 .... 3 und 8, 38 .... 3 und 8 Wie ist das mit 594 594 / 10 -> 59 594 % 10 -> 4 und 59 / 10 -> 5 59 % 10 -> 9 Hmm 594 ... 5, 9 und 4, 594 ... 5, 9 und 4 Punt 3 ****** Du brauchst eine ASCII Tabelle. Dann siehst du das die ASCII Zeichen für die Zíffern '0', '1', '2' etc alle hintereinander kommen. habe ich also zb die Zahl 5 in eine Variablen stehen, dann ergibt mir '0' + Variable genau den ASCII Code für das Zeichen '5' So und jetzt versuch noch einmal, die Funktion zu 'erklären'. Aber diesmal wirklich erklären, nicht vorlesen! Dazu ist es auch hilfreich, wenn du einmal Computer spielst, dir eine Wert für x und für kenn ausdenkst und ganz einfach auf dem Papier mal die Funktion durchspielst. Fang damit an, dir am Papier die Variablen aufzumalen x kenn i +-------+ +-------+ +------+ | 836 | | '#' | | | +-------+ +-------+ +------+ s +---+---+---+---+---+---+---+---+---+ | | | | | | | | | | +---+---+---+---+---+---+---+---+---+ Jetzt übernimmst du, und führst die Funktion aus. Aber mach nur das, was auch tatsächlich in den Anweisungen steht. Wenn an eine Variable etwas zugewiesen wird, dann radierst du den alten Wert der Variablen aus und schreibst den neuen Wert hinein (den du erhältst indem du die rechte Seite der Zuweisung ausrechnest, sofern da nicht eine konstante Zahl dasteht). Wenn eine Variable auf der rechten Seite in einer Formel verwendet wird, dann siehst du auf dem papier nach, welches der aktuelle Wert der Variablen ist. Wenn du am Ende der Funktion angelangt bist, lehnst du dirch zurück und denkst über das was du während der Abarbeitung gemacht hast nach. Wenn du dir bei einzelnen Schritten nicht sicher bist, warum sie genau so und nicht anders aussehen müssen, dann formulierst du erst mal eine Hypothese: Warum denkst du müsste das so sein. Im Idealfall kommst du dann mit einem Beispiel hoch, dass deine Hypothese stützt oder widerlegt und probierst dieses Beispiel durch. Solange, bis aus der Annahme Gewissheit geworden ist. So analysiert man fremden Code. Mit der Zeit kriegst du Übung darin und dann brauchst du zumindest für kurze Funktionen Papier und Bleistift nicht mehr. Das Prinzip ist aber dasselbe: Man geht den Code durch (entweder mit Papier oder im Kopf), vollzieht alle Operationen die im Code stehen, lehnt sich zurück und fasst das mas man gemacht hat in eigenen Worten zusammen, wobei man sich vom Code löst und auf größere Bausteine zurückgreift. Mit noch mehr Erfahrung erkennt man dann auch typische Programmstrukturen auf Anhieb und das Analysieren fällt immer leichter, weil man nicht mehr für jeden Furz den Code durchspielen muss, sondern aus der Erfahrung heraus durch Hinschauen sagen kann, was im nächsten Code Abschnitt passiert. Aber am Anfang steht: DU bist µC und DU arbeitest den Code ab.
@ R. Max Wiedersprichst du dir nicht gerade selbst? R. Max schrieb: > Daniel Lo schrieb: > > Richtig wäre: > >
1 | > while (abfrage1 == 0 || abfrage2 == 0); |
2 | >
|
> > Diese Schleife wird solange wiederholt, bis beide Abfragen gleichzeitig > einen Wert ungleich 0 liefern. So und unten hast du geschrieben R. Max schrieb: > Das ODER stimmt schon, denn die beiden Terme liefern 1, solange die > jweilige Taste nicht gedrückt ist Das würde doch bedeuten dass die Schleife garnicht ausgeführt wird, da abfrage1 und 2 den Wert 1 haben, wenn die Schalter nicht gedrückt sind. Und somit wäre die Bedingung für die Schleife schon nicht mehr erfüllt. Und eine ODER verknüpfung habe ich immer so verstanden, dass einer der Beiden nicht mehr die Bedingung erfüllen muss, um die Schleife zu verlassen. Oder irre ich mich da?
Christian D. schrieb: > So und unten hast du geschrieben > > R. Max schrieb: >> Das ODER stimmt schon, denn die beiden Terme liefern 1, solange die >> jweilige Taste nicht gedrückt ist > > Das würde doch bedeuten dass die Schleife garnicht ausgeführt wird, da > abfrage1 und 2 den Wert 1 haben, wenn die Schalter nicht gedrückt sind. > Und somit wäre die Bedingung für die Schleife schon nicht mehr erfüllt. Vorsicht. R.Max spricht von 'Termen' nicht von Eingängen. Der Term abfrage == 0 liefert eine 1, wenn die Abfrage den Wert 0 ergab
Malen wir uns doch einfach mal eine Wahrheitstabelle hin, wobei die abfrage-Variablen 1 werden, sobald die Taste gedrückt ist und termN die Vergleiche links und rechts des ODER sind:
1 | abfrage1 | abfrage2 || term1 | term2 || ergebnis | Bemerkung |
2 | ----------+----------++-------+-------++----------+------------ |
3 | 0 | 0 || 1 | 1 || 1 | Keine Taste gedrückt |
4 | 1 | 0 || 0 | 1 || 1 | Taste 1 gedrückt |
5 | 0 | 1 || 1 | 0 || 1 | Taste 2 gedrückt |
6 | 1 | 1 || 0 | 0 || 0 | Beide Tasten gedrückt |
Bei einer UND-Verknüpfung würde die Ergebinis-Spalte von oben nach unten 1 0 0 0 lauten, was nicht dem gewünschten Verhalten entspricht, daß die Schleife erst dann verlassen werden soll, wenn beide Tasten gedrückt sind. Weil das Ganze aber eigentlich eine NAND-Verknüpfung der beiden abfrage-Variablen ist, kann man die Bedingung auch so schreiben:
1 | while (!(abfrage1 && abfrage2)); |
Daraus läßt sich die Logik "solange nicht beide Tasten gleichzeitig gedrückt sind" vielleicht etwas leichter herleiten als aus der Schreibweise mit ODER und negierten Eingängen.
Ok danke, nun hab ich es verstanden, hatte das mit den Termen nicht berücksichtigt. Aber nun ist es klar. nobody is perfect :)
War ich auch drauf reingefallen. Ist ein sehr gutes Beispiel, wie man es auch nicht machen sollte, da es eben kein intuitiver Ausdruck ist. Intuitiv wäre (zumindest nach meiner Intuition):
1 | while ((abfrage1 && abfrage2) == 0) |
2 | ;
|
Das ist sicher Geschackssache, aber was findest Du an dem Vergleich mit 0, angewandt auf einen logischen Wert, intuitiver als die logische Negation (!), die ich zuletzt vorgeschlagen hatte und die sich ja auch in dem Satz wiederfindet, wenn man die Bedingung umgangssprachlich formuliert?
R. Max schrieb: > was findest Du an dem Vergleich mit > 0, angewandt auf einen logischen Wert, intuitiver als die logische > Negation (!), die ich zuletzt vorgeschlagen hatte Lutz schrieb: > Intuitiv wäre (zumindest nach meiner Intuition): Intuition läßt sich nun mal nicht erklären. Meine Denke ist da halt so. Logisch korrekt ist ja beides, aber ich würde es für mich eben so machen. Ich mag z.B. auch sehr gerne Spinat ... Na in der Richtung muß man das halt sehen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.