Hi ich hab' mir ein Muster von einem ADXL202 Beschleunigungssensor schicken lassen - der liefert ein PWM Signal - das Verhältnis ist von der Beschleunigung abhängig - jetzt hab'ich kleiner heinzi gleich mal eine Routine geschrieben die den IC auslesen soll und dass ganze an Portb mit led's darstellen soll. Irgendwann hat sich mal was getan, wenn ich die Testplatine gegen den Tisch geschlagen habe - dann hamm aber gleich alles geleuchtet - wär super wenn sich mein codevision compiler c Programm mal jemand anschauen kann........... Ich bin mir sicher, dass hätte man wesentlich intelligenter lösen können(so mit timer und so....) Ihr könnt ja mal vorschläge machen.... Freue mich auf Verbesserungen!!! Vielen lieben Dank!!!!! #include <90s2313.h> #include <delay.h> #define PWM PORTD.0 void main (void) { unsigned char zaehler1 = 0; unsigned char zaehler2 = 0; float ergebnis; DDRD=0; //auf eingang schalten DDRB=255; //auf ausgang schalten start: zaehler1=0; //zaehler auf null setzten zaehler2=0; while (PWM==1){}; //warten bis eine 0 kommt //und eine neue messung losgeht while ( PWM==0 ) //warten bis eine 1 kommt { zaehler1 ++; //zähler alle 2µshochsetzen delay_us(2); }; while ( PWM==1 ) //warten bis eine 0 kommmt { zaehler2 ++; delay_us(2); }; ergebnis=(zaehler1/zaehler2); ergebnis-=1; 1 abziehen (ich gehe von zahlen größer 1 aus) ergebnis*=100; //prozentwert ausrechnen PORTB=255; //alles nochmal ausknipsen, damit man es hernach wieder anknipsen kann - sieht man doch eh nicht in der zeit???? if (ergebnis>0)PORTB.0=0; if (ergebnis>10)PORTB.1=0; if (ergebnis>20)PORTB.2=0; if (ergebnis>30)PORTB.3=0; if (ergebnis>40)PORTB.4=0; if (ergebnis>50)PORTB.5=0; if (ergebnis>60)PORTB.6=0; if (ergebnis>70)PORTB.7=0; delay_ms(20); // a bisserl warten goto start; //neu anfangen }
:
Gesperrt durch Moderator
Hi, wie wäre es, wenn Du die PWM in eine analoge Spannung wandelst? Mit einen Kondensator und einen Widerstand. Dann das ganze auf den Analogeingang des AVR. Die Zeitkonstante der RC musst du an deine Freq anpassen. Sollte doch gehen - anders herum geht's doch auch - uC erzeugt PWM und per RC bekommt man eine analoge Spannung.... Bis dann, Ingo. PS: goto start; --> Jeder C-Programmierer hat einen Schreikrampf bekommen ;-)) Und noch ein Tipp: Verwende keine Gleitkomma-Variablen, es läßt sich so ziemlich alles mit Ganzzahlen machen. (wegen Geschwindigkeit und Speicherplatz). Am besten gar nicht erst angewöhnen.... Nur ein Rat - keine Nörgelei.
Hi Ingo Dank dir für deine Antwort!!! Das mit dem RC Glied hab' ich mir auch schon überlegt, vorallem weil es schneller geht - das Porblem im Moment ist, dass ich nur noch einen einzigen 2313 habe - gibts auch 20pinner mit AD Wandler (der 2313 hat doch keinen??) Das mit dem Schreikrampf hab' ich mir schon gedacht (hab' ich mal irgendwo gelesen) ich bin halt ein Assembler Programmierer ;-). Danke für den Rat mit den Gleitkomma-Variablen (du meinst doch das float) Vielen Dank!! mfg Christian
Moin schon wieder Ich :-) Abgesehen von den obigen Einwänden ( Goto ist basic und deshalb als Spagetticode gefürchtet ) Für Endlosschleife besser while (1) { Das ist meine Schleife } Trick : while bricht nur bei (0) ab alle anderen " Sprünge" werden über funktionen erreicht Die if Arie zum auswerten funtioniert ist aber nicht sehr elegant könnte man zb durch unsigned char Vu_meter = 0 ; for ( Ergebnis ; Ergebniss>10 ; Ergebniss/10) { Vu_meter<<1, Vu_meter++ }; PORTB=Vu_meter erledigen -> braucht weniger Speicher Der Trick funktionier so : 00000000 <<1 00000000 +1 00000001 <<1 00000010 +1 00000011<<1 PS um die Daten via RS232 ans PC Terminal zu liefern Brauchts eigentlich nur 10 Codezeilen Da kannste die Messwerte bequem am Monitor Anschauen Phagsae
Hi Phagsae Danke nochmal für deine Antwort!!!! Bevor ich dein Posting gesehen habe, habe ich mich mal mit der Mgl. mit dem AD Wandler beschäftigt und hab' für den 2333 ein Experimetierboard gebastelt (nur auf einer Lochrasterplatine) - naja und dann hab' ich das ADC Code beispiel vom Codevision getetstet - läuft aber nicht (war ja klar) - so allgemein läuft der Controller aber schon - er lässt sich immerhin programmieren......... Muss ich vielleicht eine andere externe Beschaltung nehmen um den ADC zu aktivieren oder hast du irgendeinen Vorschlag, woran das liegen kann???????????? Vielen Dank!!! mfg Christian Hier noch das Code Beispiel com codevision compiler: // I/O register definitions for AT90S8535 #include <90s2333.h> // delay functions #include <delay.h> #define ADC_VREF_TYPE 0x00 // ADC interrupt service routine interrupt [ADC_INT] void adc_isr(void) { // The LEDs will display the 8 most // semnificative ADC bits PORTB=(unsigned char) ~(ADCW>>2); // 20ms delay delay_ms(20); // Start a new AD conversion ADCSR|=0x40; } void main(void) { // Port B initialization PORTB=0xFF; // all outputs DDRB=0xFF; // all LEDs are initially off DDRD = 255; delay_ms(2000); // ADC initialization // ADC Clock frequency: 57.656 kHz // ADC Interrupts: On ADCSR=0x8E; // Global enable interrupts #asm("sei") // Select ADC input 0 ADMUX=0; // Start the first AD conversion ADCSR|=0x40; // All the job is done by ADC interrupts while (1); }
Hallo Leute ich bins wieder..... ich hirsch hab' den falschen Prozessor eingestellt gehabt (der compiler hat für einen anderen AVR Compiliert als ich eingesetzt habe - jetzt funktoniert es etwas, aber auch nicht wirklich; folgendes Problem: Die led's an denen der AD WErt ausgegebn werden schenken serh sehr schnell um - in einem Berich von2,7-2,8 Volt gehen die Led's fast schlagartig an oder aus (alle!!) - was hab' ich denn jetzt schon wieder falsch gemacht???? Es ist auch egal an welchen AD eingang ich gehe. 2. Problem - weiß jemand, wie ich das RC Glied zu dimesnionieren habe um aus einem PWM Signal mit 1000Hz meine Analoge Spannung zu bekommen????? Vielen lieben Dank für eure Antworten!!! mfg Christian
Hmmmmmm..... Moin moin Also wenn du dich um das verstehen der Ausgangssignale drücken willst ist ( Rüge!) Die PWM natürlich ne lösung aber ne gaaaaanz schlechte. :-( Wir sollten Dich schon fitmachen damit du in ein paar monaten unsere Fragen baentworten kannst :-) Als Faustformel gilt das Tau=RC ungefähr 10..100 mal dem PWM Signaltakt entspricht. ( Lade-zeit-konstante der RC combi ) #So berechnet sich übrigens die RC combi #-> Takt -> Faktor wählen 10...1000 -> Tau -> C vorgeben -> R ausrechnen Dh erst nach ca 10..100 PWM Ereignissen ist der Analogwert eingstellt Du nimmst ja ein 6dB Tiefpass und der ist logischerweise nicht mehr sonderlich schnell Bei Beschleunigungs sensoren ist meist der Impulsverlauf und der Peak wert wichtig. ( sonst kann man ja auch rechnen ) Als groben Ablauf wenns denn doch sowas wie "messen" werden soll Und nicht nur das die LED's funzeln. Zuerst die Gesamtdauer einer periode ermitteln Dann speichern = T2 Dann wie schon richtig angefangen auf Signal 1 warten Ab jetzt einfach zählen Das delay verschlechtert nur die Auflösung Als laufvariable würd ich allerdings schon ein int nehmen vieleicht brauchts sogar ein double Kommt ordentlich was an impulsen zusammen Je nach taktfrequenz des g-Sensors -> Datenblatt So jetzt der Trick: Die Low-zeit braut nicht ermittelt werden da die Gesamtperiode sich nicht ändert = T2 Die Zeit kann aber zur berechnung von g genutzt werden so das kein Messwert unausgetastet bleibt. Die Formel lautet übrigens lt Datenblatt A(g)=(T1/T2-1/2)*12,5% f ->A(g) ist logischerweise signed für T1=1/2 T2 ist dann auch der Messwert 0 Impulsbreite 1:1 Der Formel nach kann der Sensor +- 8 g bzw 1/8 = 1 g Bevor man bei der formel zum float greift hilft umskalieren ersetzt 12,5% durch 125 -> max = +- 1000 = 0x3e8 -> 3bit müssen schon sein also int -> diese vorkalkulation auch für T1 und T2 machen Da klappt auch mit dem G-messenen Phagsae
Hi Phagsae nunächst mal vielen lieben Dank für deine ausführliche Antwort. Deine Kritik am messen der analogspannung war jetzt also, dass sich die Werte über das lahme RC Glied nicht schnell genung ändern???? Außerdem ist es genauer, wenn ich das Signal direkt einlese oder???? (vermutlich muss ich deinen Beitrag nochein paar mal lesen, um ihn zu verstehen...) Das Problem beim PWM Signal ist,dass die Dauer über einen Widerstand einstellbar ist - ich also wegen den Bauteiltoleranzen nicht so genau sagen kann wieviel Prozent ich jetzt schon hab' - deshalb dachte ich mir mess ich halt mal den 2.wert mit...... Nachdem ich leicht gefrustet von der Methode mit dem AD Wandler bin stürz ich mich wieder auf die PWM Methode. Irgendwann schaff ich s schon noch...... Nochmals vielen herzlichen Dank - mal hoffen, dass es nun geht (unter berücksichtigung aller deiner Tipps ;-) MfG Christian PS: es soll tatsächlich mal sowas wie "messen" werden, nur wollte ich das erstmal testen - wie du siehst bin ich ja bereits daran gescheitert.......
Hi - ich bins scho wieder ;-) Hab' jetzt mal so rumgebazelt wie du es mir empfohlen hast (denk ich jedenfalls) - funktoniert schon wieder nicht (hab' ich mir fast gedacht) - ist aber nicht so schlimm....... Ich kommm schon noch drauf - nur hat mich jetzt wieder ein wenig der Mut und die Zeit verlassen. Würd' mich freuen, wenn du's dir mal anschauen würdest; MfG Christian #include <90s2313.h> #include <delay.h> #define PWM PORTD.0 unsigned int T2; void T2_ermitteln (void) { while (PWM==1){}; //warten bis eine 0 kommt while ( PWM==0 ) //warten bis eine 1 kommt { T2 ++; }; while (PWM==1) { T2 ++; }; } void main (void) { unsigned int T1; float Ag; unsigned char Vu_meter = 0; DDRD=0; //auf eingang schalten DDRB=255; //auf ausgang schalten T2_ermitteln(); while (1) //endlosschleife { T1=0; //zähler wieder zurücksetzen while (PWM==0){}; //warten bis eine 1 kommt while ( PWM==1 ) //warten bis eine 0 kommt { T1 ++; }; Ag=(T1/T2-0.5)*12,5; PORTB=255; //alles nochmal ausknipsen, damit man es hernach wieder anknipsen kann Vu_meter = 0; for ( Ag ; Ag>10 ; Ag/10) { Vu_meter<<1, Vu_meter++; } PORTB=Vu_meter; }; }
He da gibts ja eigentlich nix mehr zu meckern Das sollte bis auf eine kleine logelei klappen (kommt aber später) Ich verbessere noch einige kleinigkeiten die man sich nicht angewöhnen sollte bzw die das listing besser lesbar machen unsigned int T2; ### Globale declaration nur wenn nötig ### Klaut dem prozer für die gesamte Zeit ein Speicherplatz ### ob man die Variable noch braucht oder nicht void T2_ermitteln (void) { while (PWM==1){}; //warten bis eine 0 kommt while (PWM==0 ) {T2 ++;}; ## besser lesbar while (PWM==1){T2 ++;}; ## besser lesbar } ####### Besser mit return arbeiten int T_2ermitteln (void); Deklaration der Funktion int T2_ermitteln (void) { Deine funktion ## Die funktion T2_ermitteln liefer den wert T2 zurück return T2; ## Die bezeichnung ist nur lokal gültig !! ## Muss also nicht wie unten wieder an T2 übergeben werden } void main (void) { unsigned int T1; float Ag; unsigned char Vu_meter = 0; DDRD=0; //auf eingang schalten DDRB=255; //auf ausgang schalten T2=T2_ermitteln(); ###schupps Da isser wieder der T2 :-) ## aber viel eleganter und eine Speicherstelle sparend ## du kannst "T2_ermitteln" gleich in die Ag funktion einbauen ## also Ag=(T1/T2_ermitteln(void)-0,5.... usw while (1) //endlosschleife { T1=0; //zähler wieder zurücksetzen while (PWM==0){}; //warten bis eine 1 kommt while ( PWM==1 ) { T1 ++; }; Ag=(T1/T2-0.5)*12,5; < liegts am komma ??? PORTB=255; //alles nochmal ausknipsen, damit man es hernach wieder anknipsen kann Vu_meter = 0; for ( Ag ; Ag>10 ; Ag/10) { Vu_meter<<1, Vu_meter++; } PORTB=Vu_meter; ## Hier steckt der Hund !!!! ## Ich hab bei meinem Vorschlag einer gesetzt das ist latürnich nix ## Zuerst löscht du alles und dann will die Funktion einser setzten ## Da passiert natürlich nix ( zumindest nix sichtbares ) ## Die Led leuchtet ja bei 0 ## Also nich addieren sondern nur nuller einschieben }; } Hast du das mal im AVR Studio debugged ? Phagsae
Uuuuups Die Formel stimmt ja gar nicht Im Analog Device Datenblatt (Bei MAXIM hab ich den nicht gefunden) Steht (T1/T2-0,5)/12,5% int und -,5 kann probleme machen besser umformen (T1/T2-1/2)/(1/8)= 8*(T1-T2)/(T2) So ist das ohne komma und ohne float Somit kann man das float auch durch ein int ersetzten Spart wieder 4 bit Phagsae Der eben festgestellt hat das 2000 wörter doch 4k sind Somit kann ich meinen 4433 in die tonne treten Schupps sitzt der übergewichtige ATMEGA163 im Sockel Wenn schon 40polig dann aber richtig !!!!!! Muss jetzt eher schaun ob sich meine code nicht irgendwo im Speicher verirrt ( ist ja jetzt alles mit unendlichen weiten gefüllt) DA hätt ich mir jetzt gleich das LCD library schreiben sparen können Naja
Hallo Phagsae nochmals vielen lieben Dank für deine ausführliche (nächtlichen) Antworten!!!!!!! Das mit dem debuggen in AVR Studio hab' ich nun zum ersten mal pobiert und find's irgendwie komisch - wo gibts denn meine Variablen zum anschauen und wie kann ich einen Befehl überspringen ohne ihn auszuführen???? Das eigentliche Problem schaut im Moment so aus, dass die leds an PORTB immer leuchten - warum weiß ich eben nicht - selbst wenn ich hinschreibe PORTB=0; delay_ms(200) - irgendwie überreiß ich was grundlegendes an dieser lustigen Sprache wohl nicht ;-) Naja und damit hab' ich gerade die letzten 3h verbracht - irgendwie komm ich mir leicht unprodukiv vor. Mal hoffen dass du noch eine geniale Lsg auf Lager hast, damit ich wieder einen sperrlichen Schritt nach vorne mache :-) Das eigentliche Projekt ist ein Flugroboter - ich möchte mein elektroflugzeug automatisieren - im Prinzip kein großes Problem, wenn da nicht C wäre....... Aber in Assembler wird es wohl schwierig die ganzen Formeln unterzubringen - abgesehen davon kann ich nur Assembler für 8051.... Freu mich auf deine Antwort!!!!! MfG Christian
Meine Formel ist ein rechter Schhhhh... Warum fällt das keinem auf ? Phagsae ? Erweitern setzten 6 !! Hab mal in ruhe drüber nachgedacht Für einen Flugroboter ist die PWM methode geeignet Die Bewegungs Grenzfrequenz des Roboters wird ja kaum im Bereich von 100Hz liegen oder ?? Egal.... das kann man am sensor eintelllen da ist ja schon ne Filterung vorgesehen. Eigentlich würde man jetzt erstmal eine Betrachtung anstellen bzgl der maximalen Beschleunigung etc Aber das ist was fürs Physik forum Die Formel jaaaaaa.... das ist gar nicht so trival..oder eigentlich doch wenn man mal die Bretter vorm Hirn abmontiert Ich führ das mal exemplarisch vor ( Sollte mich demnächst selbst dran halten spart zeit ) 1. Mal überschlagen welche Daten denn vom Sensor kommen wenn man mal von 1ms T2 ausgeht und den uC mit 4Mhz treibt. Die while n++ schleife ( Das solle man überprüfen) wird warscheinlich aus sbrs ink in bestehen sind also ca 2+1+1 Takte eher mehr 4Mhz->1 Tkt 25 0,25 uS -> 1 Schleife 1us Messdauer 1ms ( T2) ->1ms/1us=1000 Also gehen wir mal von max 1000 Werten aus Die Formel ist mit ganzzahlen zunächst nicht brauchbar ( auch r i c h t i g umgestellt nicht ) Ag(einheit 1g)=(T1/T2 -0,5)/12,5% kommt dann richtig umgestellt auf Ag=((2T1-T2)*8)/2T2 Preisfrage kommt man mit nem int aus ? Ag kann + oder - sein also signed grösster Faktor ist (EGAL)*8 wobei 8* einem <<3 entspricht (EGAL) kann maximal 1000 werden -> 0x3E8 mal 8 ist das 0x1F40 OK mit nem normalen signed int geht das locker ABER Probleme macht (Egal)*8/T2 T2 ist einfach zu gross für Ganzzahl division >>Wer denken kann ist da klar im vorteil was soll den auch rauskommen >>wenn >>Der Messbereich des Sensors +-8g ist 255 ????? >>Brett #2 Da kann man gerade noch 1 Stelle sehen Also: Her mit dem Trick 1Ag( g ) = 1000 Ag(mg) zauber zauber...... Ag(mg)=8000*(Egal)/2T2 Ag(mg)=(8000*(2T1-T2))/2T2 Ag(mg)=(4000*(2T1-T2))/ T2 Aber 4000*1000= 4*10^6 -> also signed long int T1=250 -> -2000mg T1=500 -> 0g T1=750 -> +2000mg Das solls denn dann mal sein... Phagsae
Hi Phagsae nochmals vielen lieben Dank für deine zahlreichen ausführlichen Antworten und deine Ausdauer, die du mit entgegebracht hast ;-) Es funktioniert jetzt (endlich)!!!!! Irgendwie ist noch ein kleiner Wurm in der Schleife drin, die die LED's an und aus schaltet - ist aber nicht so schlimm. Der Sensor liefert irgendwie ein wenig zittrige Werte - die led's zittern teilweise sogar im Ruhezustand, obwohl die so eine schlechte Auflösung haben. In einem anderemPostin hast du mal geschrieben,dass du studiert hast - was denn und was machst du jetzt????? Danke nochmals für deine Unterstützun - langsam macht C spaß mfg Christian
Danke fürs Bartkraulen :-) Aber so nett binn ich gar nicht. Hab ja auch mal so nebenbei was Gelernt. Ich weiss ja jetzt das es interessant Beschl Sensoren gibt wie man sie ausliest und welche Formel wohl funktioniert bzw wie die Auswertung beschaffen sein muss. Wie du an der Formel sehen konntes ist ja auch oft unausgegorener Quatsch dabei. Hast du ein Oszi ? und ein Signalgenerator ? Dann überprüf doch mal ob der Output auch mit den Messergebnissen übereinstimmt. Oder mach mit dem TIMER2 mal ne PWM die du dann dem Messeingang zuführst. ( ich hoffe das geht is auch nur ne uaQ Idee ) Oder mach beides über die Soundkarte und entsprechender Software. Der AVR kann ja mit beliebig kleinem Takt arbeiten nennt sich "full static" Als wirklich gute debbug methode hat sich für mich das anzeigen best Zustände via UART auf dem PC herausgestellt ) Mach starte ein neues Projekt Und aktiviere im CVR Code Wizard einfach die RS232 Verbinde TX RX mit deinem PC Wenn du keine fertige Schnittstelle hast hilf da ein MAX323 plus 4 Cond Dann schreib ein putchar( char ) ein zeichen richtung stdio ist immer auf RS232 eingestellt sofern man das nicht ändert Zeichenketten gehen via printf("Laberrabarber", ptoTEXT ) ptoTEXT ist ein zwischenpuffer der als char ptoTEXT[] angelegt wird Der CVAVR hat reduzierten formatierungs befehle Das kann aber vorher ausgeglichen werden Das Zittern kann normal sein Welche Werte gibst du denn in die LED Kette ? 1 mg kann der sensor eigentlich gar nicht auflösen Ich wollt nur nicht so exotische einheiten wie 10-2 g einführen Als kleinste einheit konnte der glaube ich 10mg ( ? ) Je nach lage müsste er ja auch 1g durch die Erdanziehung anzeigen. Macht er das ?
Beitrag #7834628 wurde von einem Moderator gelöscht.
Beitrag #7834647 wurde von einem Moderator gelöscht.
Beitrag #7834671 wurde von einem Moderator gelöscht.
Beitrag #7834704 wurde von einem Moderator gelöscht.
Beitrag #7834713 wurde von einem Moderator gelöscht.
Damit man den ADXL202 nicht aus dem Museum klauen muß, der ADXL312 dürfte als Ersatz geeignet sein. Er kann direkt über I2C oder SPI ausgelesen werden. Falls man aber doch PWM einlesen muß, dann wurde dafür die Input Capture Funktion implementiert. Von hinten durch die Brust ins Auge über RC-Filter und ADC ist sowas von unnötig. Input Capture läßt sich auch für mehrere Eingänge über den ADC-Multiplexer nacheinander verwenden. Float ist natürlich auch auf ATtiny verwendbar, jede Angst davor ist völlig unbegründet. Natürlich muß man dann aber auch in float rechnen und nicht erst das Endergebnis nach float zuweisen.
:
Bearbeitet durch User
Beitrag #7834735 wurde von einem Moderator gelöscht.
Beitrag #7834740 wurde von einem Moderator gelöscht.
Bernd S. schrieb im Beitrag #7834735: > mal auf's Datum geachtet? > der thread ist schon 1/4 Jahrundert alt..... Ja, aber denk immer daran, Heute gibt es Verbesserungen, die es vor 23 Jahren noch nicht gab! Und wenn das am Ende zu einer Lösung führt, dann ergibt das einen durch und durch abgerundeten Thread mit einem guten Ergebnis und einem guten Lesegefühl. Das macht Laune!
Marcel V. schrieb: > Ja, aber denk immer daran, Heute gibt es Verbesserungen, die es vor 23 > Jahren noch nicht gab! Deshalb muss man aber trotzdem nicht jeden vierteljahrhundert alten Thread rauskramen. Allerdings war der ursprüngliche Kramer ein anderer. Ich mache mal den Thread dicht, dass der nicht noch zu neuem Leben erwacht.