Einen Feelspace Belt mit Arduino bauen und programmieren (Teil 2): Der TE669 Multiplexer

In unserem zweiten Teil gucken wir uns eines der Bauteile genauer an: den TE669 Multiplexer, den wir zur Ansteuerung der Motoren unseres Projekts benötigen. Das Breakout Board ist mit einem CD74HC4067 Analog/Digital Multiplexer Chip ausgestattet. Ein Multiplexer ermöglicht es, über Boolsche Logik kombinatorisch ein Signal über mehrere Aus/Eingänge zu leiten. Dies geschieht maximal jeweils in Potenzen von 2: Verwendet man einen Anschluss auf dem Board, kann man zwei logische Zustände erzeugen, bei jedem weiteren noch einmal zwei verketten, also 2/4/8/16. Das TE669 Board hat vier Steuerungsanschlüsse, entsprechend also 2^4=16 Ein/Ausgänge, über die das Signal geschaltet werden kann. In der Elektronik wird ein Multiplexer oft mit MUX oder Mux abgekürzt. Hier ein Schema des Boards, kurz erklärt:

C0 bis C15 auf der linken Seite sind die 16 Ein/Ausgänge, die der Multiplexer ansprechen/lesen kann. Bei uns also schlicht die Stromleitungen für die Vibrationsmotoren. SIG ist die Quelle bzw. der Eingang des Signals. S0 bis S3 sind die Steuerungspins, die über On/Off entscheiden, welcher der Kanäle auf der linken Seite gerade SIG sendet/empfängt. VCC wird über 5V angeschlossen, GND eben an GND. EN steht für „Enable“. Setzt man diesen Pin unter Strom, werden alle Signale auf „Off“ gesetzt. Weil wir keinen Schalter brauchen, wird er mit GND verbunden.

Der analoge Teil interessiert uns nicht, weil wir lediglich digital 5 Volt On/Off an Vibrationsmotoren weiterleiten wollen, die Programmierung ist aber praktisch gleich, weil analoge ebenso wie digitale Signale über den SIG-Pin weitergegeben werden. Man muss das Rad nicht neu erfinden, für das Board steht eine hervorragende Bibliothek auf Github zur Verfügung. Diese muss nur als .zip-Datei heruntergeladen und in der Arduino IDE importiert und eingebunden werden.

Um die Verlötung zu testen (und weil ich mit dem Kompassmodul massive Schwierigkeiten hatte, davon im nächsten Teil) nutzen wir das mitgelieferte Beispiel, das alle I/O einmal mit dem Signalpin anspricht:

 

#include <CD74HC4067.h>

// s0 s1 s2 s3
CD74HC4067 my_mux(4, 5, 6, 7); // create a new CD74HC4067 object with its four control pins

const int g_common_pin = 8; // select a pin to share with the 16 channels of the CD74HC4067

void setup()
{
 pinMode(g_common_pin, OUTPUT); // set the initial mode of the common pin.
 // This can be changed in loop() for for each channel.
}

void loop()
{
 digitalWrite(g_common_pin, HIGH);

for (int i = 0; i < 16; i++) {
 my_mux.channel(i);
 delay(100);
 }
}

In der ersten Zeile Code müssen die digitalen Ausgänge, die S0-S3 ansprechen, angegeben werden. Dann wählt man den Signalpin auf dem Board, in meinem Fall der digitale Pin 8. Damit ist auch schon alles erledigt, die Anschlusslogik müssen wir dank der Bibliothek nicht selbst programmieren. Anschließend wird das HIGH Signal in einer Schleife über alle Ausgänge des Multiplexers geschickt. Das sieht dann so aus (eine LED ist falsch verkabelt):

Anschließend setzen wir einfach einen Motor dran, um den Betrieb zu testen. Das läuft wunderbar. Nachdem das Signal durch den Mux gelaufen ist, trägt es nur noch 3.75 Volt, was wie mein Multimeter mir sagt, was ideal für die Motoren ist, die sonst auf Überspannung laufen würden. Achtung: Das gilt nur, solange im Multiplexermodul nicht der VCC verkabelt ist. Sobald der angeschlossen ist, werden die vollen 5V übertragen.

Das Ziel der Programmierung sollte nun klar sein: Das Kompassmodul gibt Gradwerte von 0°-359.9° aus. Entsprechend der Position im Magnetfeld muss der my_mux.channel()-Wert angepasst werden. Da es mit dem Sensor Probleme gab, simulieren wir diese Werte über einen Joystick. Entsprechend dessen Gradposition (wir nehmen 0° als Norden an) können wir dann die unterschiedlichen LEDs leuchten lassen, was auch genau der Ansteuerung der Motoren später entspricht. Hier der Code:

#include <math.h>
#include <CD74HC4067.h>

// s0 s1 s2 s3
CD74HC4067 my_mux(4, 5, 6, 7); // create a new CD74HC4067 object with its four control pins

const int g_common_pin = 8; // select a pin to share with the 16 channels of the CD74HC4067



int range = 500; // output range of X or Y movement
int responseDelay = 5; // response delay of the mouse, in ms
int threshold = 10; // resting threshold
int center = range / 2; // resting position value



void setup() {
 // put your setup code here, to run once:
Serial.begin(9600);
 pinMode(g_common_pin, OUTPUT);
}

void loop() {
int xReading = readAxis(A0);
int yReading = readAxis(A1);

Serial.println("X Value: "+String(xReading)+" Y Value: "+String(yReading));

double degree = findDegree(xReading,yReading);

Serial.println("Degree: "+String(degree));

delay(50);

int northMux = defineMuxFromDegree(degree);

my_mux.channel(northMux);
digitalWrite(g_common_pin, HIGH);

Serial.println("Mux Channel: "+String(northMux));

}

int readAxis(int thisAxis) {
// read the analog input:
int reading = analogRead(thisAxis);

// map the reading from the analog input range to the output range:
reading = map(reading, 0, 1023, 0, range);

// if the output reading is outside from the rest position threshold, use it:
int distance = reading - center;

if (abs(distance) < threshold) {
distance = 0;
}

return distance;
}

 

double findDegree(double x, double y){
double value = (atan2(x, y) / M_PI) * 180;
if(value < 0) value += 360;
return value;
}

int defineMuxFromDegree(float muxdegree){
if (muxdegree<=11.24||muxdegree>=347.75) {return 0;}
if (muxdegree>=11.25&&muxdegree<=33.74) {return 1;}
if (muxdegree>=33.75&&muxdegree<=56.24) {return 2;}
if (muxdegree>=56.25&&muxdegree<=78.74) {return 3;}
if (muxdegree>=78.75&&muxdegree<=101.24) {return 4;}
if (muxdegree>=101.25&&muxdegree<=123.74) {return 5;}
if (muxdegree>=123.75&&muxdegree<=146.24) {return 6;}
if (muxdegree>=146.25&&muxdegree<=168.74) {return 7;}
if (muxdegree>=168.75&&muxdegree<=191.24) {return 8;}
if (muxdegree>=191.25&&muxdegree<=213.74) {return 9;}
if (muxdegree>=213.75&&muxdegree<=236.24) {return 10;}
if (muxdegree>=236.25&&muxdegree<=258.74) {return 11;}
if (muxdegree>=258.75&&muxdegree<=281.24) {return 12;}
if (muxdegree>=281.25&&muxdegree<=303.74) {return 13;}
if (muxdegree>=303.75&&muxdegree<=325.24) {return 14;}
if (muxdegree>=325.25&&muxdegree<=347.74) {return 15;}
}

Läuft alles, und wenn wir den Joystick nun einmal im Kreis drehen, leuchtet unsere LED-Reihe einmal der Reihe nach auf. Jetzt müssen da nur noch Motoren statt LEDs ran und die Daten aus dem Kompass/Gyroskop-Sensor kommen. Davon im nächsten Teil!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

*