Hallo liebe Community, Momentan bin ich dabei mein Inkrementalmesssystem (Anbaumessschieber von Wabeco) mit einem XMega zu verheiraten, damit ich diesen an meiner Fräse anbauen kann... In diesem Beitrag wollte ich die Fachmeinung der Kenner wissen (bin selbst kein Elektrotechniker). Zur Allererst habe ich mit einem Oszilloscop die Ausgänge des Messschiebers überprüft. Ich messe auf der Taktleitung ein Paket, welches etwa 12,5 ms lang ist, danach kommt 170 ms nichts dann kommt das gleiche Paket wieder. Ein Bild des Oszis ist angehängt Oszi1.PNG. ----------------Oszi1.PNG----------------- Anscheinend arbeitet der Messschieber intern in 1/100 mm, denn wenn ich die Messleiste um 0,01 mm verschiebe, so verschwindet auf der Datenleitung (Gelb) das erste "Bit" (oder wie heißt es in den Fachkreisen?). Die negativen Werte sieht man anhand des letzten Paket. Denn dort wird der erste Bit dann "Low" (die restlichen überflüssig). Zu sehen in dem Bild Oszi2.PNG ----------------Oszi2.PNG----------------- Um die Daten auszulesen brauche ich also nur 2 Pins. Bei diesen wird dann der Zustand verglichen und bei Übereinstimmung ist der Bit 0 bei Nichtübereinstimmung ergibt es eine 1. Sollte man eine Funktion zum vergleichen schreiben, welche dann binären Wert liefert. Auf diese Funktion wird von einer anderen Zugegriffen, welche den Wert dann zusammensetzt zu einem Integer. Und dieser Integer ist mein Messwert. ----> Zu den Fragen <---- 1.) Ist der Gedankengang ok? 2.) Gibt es eine elegantere Methode den Pegel auszulesen? 3.) Meinen XMega will ich mit 3,3 V Betreiben (denn sonst mein LCD-Modul Probleme macht), der Messschieber arbeitet bei 1,5 Volts. Ich will einen 4fachen Operationsverstärker nehmen und diesen in einer nichtinvertierender Verstärkerschaltung betreiben um die Spannung zu verdoppeln (zwei TS272). Ist es eine optimale Lösung? 4.) Idee ist, dass der Mikrokontroller eine lineare Regression ausführt und intern nach einer Kalibrierung mittels Prüf-Messwerte die Berechneten(theoretisch richtigen) Werte für die Messung anzeigt. Schafft ein Mikrokontroller eine Lineare Regression zu berechnen? Und das Alles soll für 4 Messschieber Funktionieren!?!? Ich bitte sie um konstruktive Beiträge Viele Grüße Alex
Du kannst z.B. die vorhandene SPI-SChnittstelle von Deinem XMega benutzen, die ist speziell für sowas gemacht. Dann liest Du 3 Byte ein und baust daraus ein Long integer, damit kannst Du alle Werte abbilden, die das Ding liefern kann. Zur Anpassung der Pegel gibt es Artikel in der Artikelsammlung. "lineare Regression" ist ein bischen hochgreifend formuliert. Wieviele Kalibrierungspunkte hast Du denn? Wenn es nur Anfang und Ende mit den jeweiligen Messwerten sind, dann ist der Rest ein Dreisatz. Dass schafft der uC.. :-) Für 4 Signale kannst Du entweder mehrere SPI -Schnittstellen als Software emulieren, oder Du baust Dir aus Logikbausteinen einen Umschalter, mit dem Du immer nur ein Leitungspaar zur SPI durchlässt.
Danke für deine Antwort! SPI zu benutzen ist eine sehr gute Idee. Habe mir nun eine Bidirektionalen 8-Bit Pegelwandler besorgt, durch den ich meine 3,3V für Mikrocontroller bekomme. Habe bischen im Datenblatt des X-Mega's bezüglich der SPI-Interfaces gelesen. Da steht, dass man ja nur 4 Register braucht. Das CTRL, INTCTRL, STATUS und DATA. In das CTRL-Register schreibe ich eine 0x6C da es ja gerade meinen einstellungen entspricht: 01101100 (Clock-Double ist --> 0, SPI-wird eingeschaltet --> 1 ; LSB first --> 1 ; Slave-Modus --> 0 ; SPI-Mode 3 --> 1 --> 1 und Prescaler --> 0 --> 0 ) das in Hexadezimal: 0x6C, also CTRL = 0x6C. Das INTCTRL setze ich 0. Wenn ich nun auf dem Steckboard das alles verdrahte und LCD anschließe, so bekomme ich wirre werte... Mit dem STATUS Register habe ich schwierigkeiten... Ich Kriege je von dem Messschieber 24 Bits, das sind 3 mal 8-Byte Pakete. Ich muss also irgendwie den DATA-Register mit hilfe des STATUS Registers 3 mal pro Datenübertragung auslesen und dabei einen uint32_t erzeugen ?.?.?.? weiß momentan nicht weiter. Kann mir eventuell jemand Literaturhinweis geben? Hier mein Code:
1 | /*
|
2 | * ATXmega16A4_AU.c
|
3 | *
|
4 | * Created: 01.10.2012 21:06:30
|
5 | * Author: Alex
|
6 | */
|
7 | |
8 | #define F_CPU 32000000UL
|
9 | #define FALSE 0;
|
10 | #define TRUE 1;
|
11 | |
12 | |
13 | #include <avr/io.h> |
14 | #include <util/delay.h> |
15 | #include "lcd-routines.h" |
16 | |
17 | // Das ist eine Funktion zur Einstellung des internen 32 MHz Schwingers
|
18 | |
19 | void Clock_init(void) |
20 | {
|
21 | OSC.CTRL |= OSC_RC32MEN_bm; |
22 | while(!(OSC.STATUS & OSC_RC32MRDY_bm)); |
23 | CCP = CCP_IOREG_gc; |
24 | CLK.CTRL = 0x01; |
25 | }
|
26 | |
27 | int main(void) |
28 | {
|
29 | Clock_init(); |
30 | |
31 | lcd_init(); |
32 | |
33 | SPIC.CTRL = 0x6C; //Setzen des CTRL-Registers |
34 | SPIC.INTCTRL = 0; |
35 | uint32_t i = 0; |
36 | char puffer[20]; |
37 | lcd_clear(); |
38 | lcd_string("Anzeige: "); |
39 | |
40 | while(1) |
41 | {
|
42 | i = SPIC.DATA; |
43 | ultoa(i, puffer, 10 ); |
44 | lcd_setcursor(9,1); |
45 | lcd_string( puffer ); |
46 | _delay_ms(10); |
47 | }
|
48 | |
49 | return 0; |
50 | }
|
---------------- Zur Linearen Regression ------------------ Zur Kalibrierung habe ich 7 Wertepaare alle symmetrisch entlang 175 mm verteilt mit Genauigkeit von unter pm 0,01 mm. Die Abschätzung des Quadrat der Standartabweichung lautet:
Nun minimiert man die Parameter bezüglich a und b:
ergibt sich das Gleichungsystem:
Als Lösung des Gleichungsystems erhält man:
und für den Linearen Koeffizienten b:
Hier ist D die Determinante und beträgt:
Wie man nun sieht müssen die 3-fachen Produkte berechnet werden über die Summen der Wertepaare. hmmm Schafft der Mikrokontroller das?
Alexej W. schrieb: > Zur Kalibrierung habe ich 7 Wertepaare alle symmetrisch entlang 175 mm > verteilt mit Genauigkeit von unter pm 0,01 mm. Und wie liegen deine Werte in Relation zu einer Geraden. Eine Kalibrierung ist nur sinnvoll, wenn der Zusammenhang reproduzierbar ist und nicht bei der nächsten Kalibiermessung ganz anders aussieht. Ggf. benötigt man z.B. zusätzlich einen Temperaturfühler für Korrekturen.
Japp das ist dann für Später als Erweiterung gedacht. Aktuell lese ich die Werte manuell ab und berechne diese mit einem kleinen Progrämmchen, die Berechnung dauert zwar kurz auf meinem Werkstatt-Rechner, geht aber. Die Werte weisen eine sehr gute Linearität auf, so dass es wie oben erwähnt nur von der Umgebungstemperatur und dem linearen Wärmeausdehnungskoeffizienten abhängt. Später wollte ich einen PT100 oder sowas an Mikrokontrollen anschließen, welcher dann vergleicht ob die Temperatur im Raum sich geändert hat oder nicht und dann etscheidet ob eine neue Kalibrierung vorgenommen werden muss....
Hallo, Bitte um Hilfe bezüglich Code... Habe nun bischen recheschiert und herausgefunden was ich brauche, es klappt jedoch nicht! Ich muss also 3 Bytes nacheinander auslesen und diese dann in ein uint32_t zusammenfügen. Danach muss ich ja den Wert einmal spiegeln und dann ist er theoretisch fertig. Hier mein Code:
1 | /*
|
2 | * ATXmega16A4_AU.c
|
3 | *
|
4 | * Created: 01.10.2012 21:06:30
|
5 | * Author: Alex
|
6 | */
|
7 | |
8 | #define F_CPU 32000000UL
|
9 | #define FALSE 0;
|
10 | #define TRUE 1;
|
11 | |
12 | |
13 | #include <avr/io.h> |
14 | #include <util/delay.h> |
15 | #include "lcd-routines.h" |
16 | |
17 | |
18 | //Funktion zur Einstellung des internen 32 MHz Schwingers
|
19 | void Clock_init(void) |
20 | {
|
21 | OSC.CTRL |= OSC_RC32MEN_bm; |
22 | while(!(OSC.STATUS & OSC_RC32MRDY_bm)); |
23 | CCP = CCP_IOREG_gc; |
24 | CLK.CTRL = 0x01; |
25 | }
|
26 | |
27 | //SPI-Schnitstelle Initialisieren
|
28 | void Spi_init(void) |
29 | {
|
30 | SPIC.CTRL = 0b01101100; //Control-Register: 0b01101100 -> (Clock-Double -> 0, SPI einschalten -> 1, LSB first -> 1, Slave-Modus -> 0, SPI-Mode 3: -> 1 -> 1, Prescaler: -> 0 -> 0) |
31 | SPIC.INTCTRL = 0x00; //Interrupt-Register: 0b00000000 -> (Reserviert -> 0 -> 0 -> 0 -> 0 -> 0 -> 0, Interrupt-Level: OFF -> 0 -> 0 ) |
32 | }
|
33 | |
34 | //3 Bytes aus dem SPI Auslesen und in ein uint32_t reinschreiben
|
35 | uint32_t spi_bytes_empfangen(void) |
36 | {
|
37 | uint32_t data = 0; |
38 | data = SPIC.DATA; //Daten-Register auslesen |
39 | data <<= 8; //data um 8 Bits nach links schieben |
40 | data |= SPIC.DATA; //hänge ein Byte aus dem Daten-Register rechts an data an |
41 | data <<= 8; //data um 8 Bits nach links schieben |
42 | data |= SPIC.DATA; //hänge ein Byte aus dem Daten-Register rechts an data an |
43 | return data; //Ausgabe des data-Wertes |
44 | }
|
45 | |
46 | //Spiegelung eines uint32_t, hier wird bitweise der neue uint32 zusammengesetzt
|
47 | uint32_t spiegelnuint32(uint32_t input) |
48 | {
|
49 | uint32_t output=0; |
50 | for(uint8_t i=1;i<=32;i++) |
51 | {
|
52 | output |= input & i << (32-i); |
53 | }
|
54 | return output; |
55 | }
|
56 | |
57 | int main(void) |
58 | {
|
59 | Clock_init(); |
60 | Spi_init(); |
61 | lcd_init(); |
62 | |
63 | uint32_t i; |
64 | char puffer[20]; //Anlegen eines Strings von Länge 20 Zeichen |
65 | lcd_clear(); |
66 | lcd_string("Anzeige X: "); |
67 | |
68 | while(1) |
69 | {
|
70 | i=0; |
71 | i = spiegelnuint32(spi_bytes_empfangen()); //Hier wird nun der empfangene uint32_t gespiegelt und dem i zugewiesen |
72 | ultoa(i, puffer, 10 ); //Funktion zur Umwandlung eines Unsignet-Longs zu String puffer in der Dezimalen Darstellung |
73 | lcd_setcursor(11,1); |
74 | lcd_string( puffer ); |
75 | }
|
76 | |
77 | return 0; |
78 | }
|
Wenn ich das Programm compiliere, so sehe ich auf dem LCD als Position 0, sobalt ich den Messchieber um 0,01mm bewege ändert sich der Wert sofort auf 05792. Bei Wert 0,02 mm ist LCD bei 031586. Wenn ich nun den Messschieber resete, dann ist die LCD-Anzeige bei dem alten Wert, obwohl nach einem Reset die Data-Leitung eine 0 liefert... Sehe momentan keinen Fehler im Code. Bitte um Hilfe Grüße Alex
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.