Hallo upaucc,
sorry – ich habe erst jetzt ein wenig Zeit gefunden, Dir zu antworten.
Lass uns mal kleine Schritte machen – sonst liest das keiner
In der ersten Folge wollen wir uns mal mit der PollSwitch()-Funktion beschäftigen.
Dazu ist ein Blick in die Schaltung noch mal recht hilfreich. Die Schalter werden nämlich nicht direkt gelesen - dann würde man 6 digitale Eingänge benötigen. Da man Prozessorpins sparen wollte (Geiz ist also auch bei Robotern geil) misst man die Spannung über dem Spannungsteiler R23 und R25-30. Ist kein Schalter gedrückt, dann liegt an diesem Punkt die Betriebsspannung V+ an (jedenfalls nach einer gewissen Zeit, was mit dem Kondensator C7 zu tun hat – aber zu dem kommen wir später).
Wird ein Schalter betätigt, so fließt durch den zugehörigen Widerstand Strom und die Spannung am PIN 27 (ADC4) sinkt. Da nun jeder Schalter mit einem anderen Widerstand verbunden ist, ist die Spannung jedes Mal verschieden. Damit könnte man eine Tabelle anlegen, die für jeden Schalter die entsprechende Spannung enthält und wüsste somit, welcher Schalter gedrückt wurde. Wie groß müsste diese Tabelle sein? Nein, es reicht nicht aus dort 6 Werte einzutragen sondern es müssen auch alle möglichen Kombinationen der Schalter berücksichtigt werden. Man braucht also 2^6=64 Tabelleneinträge! Und durch die Toleranzen der Widerstände bedingt, müsste diese Tabelle für jeden ASURO speziell erstellt werden! Darum haben die Entwickler zu einem genialen Trick gegriffen – sie haben die Widerstände so gewählt, dass man errechnen kann, welche Tasten gedrückt wurden!!! Und genau das macht PollSwitch():
1024.0/(float)i - 1.0)) * 63.0 + 0.5)
Die Herleitung dieser Formel überlasse ich Dir – Du kannst Sie aber im Buch „Mehr Spaß mit Asuro – Band 1“ finden.
Das Ergebnis der Berechnung soll so sein, dass für jeden Schalter das entsprechende Bit gesetzt ist, wenn er gedrückt wurde – auch in Kombinationen mit anderen Schaltern.
Soweit die Theorie – und jetzt noch ein Wort zur wirklichen Welt:
Auf Grund der Bauelementetoleranzen kann es sein, dass der Faktor 63 nicht passt – dann muss man damit einwenig experimentieren. Außerdem treten in der Schaltung Störimpulse auf, die von den Motoren verursacht werden. Der Kondensator C7 soll diese glätten. Leider erkauft man sich diesen Vorteil mit dem Nachteil, dass der Kondensator eine gewisse Zeit braucht, bis er auf die Spannung des Spannungsteilers aufge- oder entladen hat. Aus diesem Grunde muss man etwas warten, bis der Wert am AD-Wandler stabil ist.
So, und jetzt zum Programm:
Ich habe als Vorlage mal den Auslieferungszustand genommen – also asuro.c und asuro.h so, wie sie auf der CD - sind. Am Anfang gibt es ein paar Hilfsfunktionen für die Ausgabe, die ich aus der Lib2.7 entliehen habe. Die Funktion Pause() dient nur dazu, den Output in Terminal-Fenster zu bremsen.
Dann habe ich die Funktion PollSwitch() aus asuro.c kopiert und umbenannt (ich hätte sonst die Funktion in der asuro.c auskommentieren müssen, was auch möglich gewesen wäre).
Und jetzt kann ich mit der Funktion machen, was ich will – ist ja meine
Ich habe ein paar Kommentare rein geschrieben und die Werte für die Rohdaten des AD-Wandlers und die berechneten Daten der Schalter ausgegeben.
Schau doch mal, was das Terminalprogramm ausgibt, wen Du keine Tasten drückst und was es ausgibt, wenn du eine beliebige Tastenkombination drückst. Schreibe Deine Ergebnisse hier rein und wir schauen dann weiter…
Code:
#include "asuro.h"
void UartPutc (unsigned char zeichen)
{
UCSRB = 0x08; // enable transmitter
UCSRA |= 0x40; // clear transmitter flag
while (!(UCSRA & 0x20)) // wait for empty transmit buffer
;
UDR = zeichen;
while (!(UCSRA & 0x40)) // Wait for transmit complete flag (TXC)
;
}
void SerPrint(char *data)
{
unsigned char i = 0;
while (data[i] != 0x00)
UartPutc(data [i++]);
}
void PrintInt(int wert)
{
char text [7]; // "-12345"
itoa(wert, text, 10);
SerPrint(text);
}
void Pause(void)
{
int i;
for (i=1; i<250; i++) Sleep(255);
}
/* function to read out switches */
unsigned char _PollSwitch (void)
{
unsigned int i, Schalter;
DDRD |= SWITCHES; // Switches as Output
SWITCH_ON; // Output HIGH for measurement
ADMUX = (1 << REFS0) | SWITCH; // AVCC reference with external capacitor
Sleep(10);
ADCSRA |= (1 << ADSC); // Start conversion
while (!(ADCSRA & (1 << ADIF)));// wait for conversion complete
ADCSRA |= (1 << ADIF); // clear ADCIF
i = ADCL + (ADCH << 8);
SWITCH_OFF;
/* Hier wurde der Wert für die Schalter ausgelesen. Also schauen
* wir uns den mal an:
*/
SerPrint("\r\n\r\nAD-Wandlerwert der Schalter: ");
PrintInt(i);
/* Und erst jetzt wird versucht, den Spannungswert in ein Bitmuster
* für die Schalter umzurechnen. Also schauen wir uns den Wert auch
* an:
*/
Schalter = ((unsigned char) ((( 1024.0/(float)i - 1.0)) * 63.0 + 0.5));
SerPrint("\r\nGedrückte Schalter: ");
PrintInt(Schalter);
/* Sollte jetzt der Wert nicht dem erwarteten entsprechen, musst Du
* den Wert 63.0 solange ändern bis es für alle Schalter passt!
*/
return Schalter;
}
int main(void){
while(1)
{
_PollSwitch();
Pause(); // nur damit die Daten nicht wie wild über den Bildschirm sausen
}
}
Viel Spaß,
_HP_
Lesezeichen