2 Hall-Sensoren sollen Drehung und Position erkennen

Hallo,
es geht darum einen Handgriff zu bauen. Er soll nicht ganz rumdrehen, also ca. 350°. Werte von 0 bis 1023, wird via Arduino Micro als Joystick verwendet.

Für Poti oder Drehencoder finde ich keine Möglichkeit.

Man könnte ja 2 digitale Hall-Sensoren mit vielen Magneten im Griff wie einen Drehencoder benutzen, aber dann ist mir die Auflösung zu gering.

Meine letzte Idee sind 2 lineare Hall-Sensoren zu benutzen, aber da reichen meine Programmierkenntnisse nicht.
Gibt es vielleicht schon ein fertiges Projekt, oder ein Schubbs in die richtige Richtung?

Danke schonmal,
Chris...

Ich habe mal einen Test mit 2 digitalen Hall-Sensoren (A3144) und 6 Magneten gemacht (alle der Reihe nach mit wechselnder Polarität).
Damit kann ich 0 bis 12 Schritte auswerten.

Aber wie gesagt, benötige ich eine höhere Auflösung, deshalb meine idee mit den linearen Hall-Sensoren (49E).

Gibt es fertig von einigen Herstellern.

Kann man sich auch selber basteln

Interessant. Ich komme jedoch leider nicht an den Mittelpunkt heran, weshalb sich Poti und RE ausschließen. Ich benötige etwas was mit mehreren Magneten funktioniert.

Ein letzter Vorschlag:
Optisch - GrayCode

Ich habe mir eine Konstruktion ausgedacht mit 52 kleinen Magneten (1mm Durchmesser x 1mm Länge). Macht 104 Schritte hochgerechnet und auf 1023 begrenzt.
Das reicht vermutlich dicke, da brauche ich keine echten 1023 Schritte

Es gibt Hallsensoren die die Position eines einzigen Magneten erkennen und dadurch die Winkelposition errechnen.
lies mal:

Grüeße Uwe

versteh ich nicht. Oben schreibst du dass du den Griff selber bauen willst. Dann bau ihn so dass der drehpunkt erreichbar ist.

Ansonsten es gibt ja auch Schiebepotis, da muss man nicht an den Drehpunkt und könnte man mit einem Hebel betätigen.

Eine Zeichnung von dir könnte Licht in die Raterei bringen.

Ich habe einen Ring mit 80 Magnete gebaut, die sich in der Polarität abwechseln.


Der ist mit dem Drehgriff verbunden.

Am starren Teil gegenüber sind besagte Hall-Sensoren A3144 verbaut, die an den Arduino Micro angeschlossen sind.

Funktioniert tadellos, WENN man langsam dreht. Dreht man zu schnell, gibt es Schrittverluste. Mal sehen, ob Interrupts das Problem verbessern, derzeit arbeite ich ohne. Ich galube aber eher, dass die Magnete zu schwach sind.

Ich behaupte: Nein.

Ich behaupte: Nein.

Eine Idee was es sonst sein könnte?

Meine Glaskugel sagt:

Der Nächste antwortet mit :
Dein geheimer Sketch

#include <Encoder.h>
#include <Joystick.h>

bool report = true;
//bool report = false;
float maxenccount = 150; // max 154
/*      Joystick      */
uint8_t hidReportId = 0x03; // - Default: 0x03 - Indicates the joystick's HID report ID. This value must be unique if you are creating multiple instances of Joystick. Do not use 0x01 or 0x02 as they are used by the built-in Arduino Keyboard and Mouse libraries.
uint8_t joystickType = JOYSTICK_TYPE_JOYSTICK; // - Default: JOYSTICK_TYPE_JOYSTICK or 0x04 - Indicates the HID input device type. Supported values:
uint8_t buttonCount = 10; //- Default: 32 - Indicates how many buttons will be available on the joystick.
uint8_t hatSwitchCount = 0; // - Default: 2 - Indicates how many hat switches will be available on the joystick. Range: 0 - 2
bool includeXAxis = 0; // - Default: true - Indicates if the X Axis is available on the joystick.
bool includeYAxis = 0; // - Default: true - Indicates if the Y Axis is available on the joystick.
bool includeZAxis = 0; // - Default: true - Indicates if the Z Axis (in some situations this is the right X Axis) is available on the joystick.
bool includeRxAxis = 1; // - Default: true - Indicates if the X Axis Rotation (in some situations this is the right Y Axis) is available on the joystick.
bool includeRyAxis = 1; // - Default: true - Indicates if the Y Axis Rotation is available on the joystick.
bool includeRzAxis = 0; // - Default: true - Indicates if the Z Axis Rotation is available on the joystick.
bool includeRudder = 0; // - Default: true - Indicates if the Rudder is available on the joystick.
bool includeThrottle = 0; // - Default: true - Indicates if the Throttle is available on the joystick.
bool includeAccelerator = 0; // - Default: true - Indicates if the Accelerator is available on the joystick.
bool includeBrake = 0; // - Default: true - Indicates if the Brake is available on the joystick.
bool includeSteering = 0; // - Default: true - Indicates if the Steering is available on the joystick.

/*      Gyro      */
float smooth = 50;
float sPitch=0, j=10;
float smoothPin = A2;

#include <Wire.h>
#include <Adafruit_MCP23X17.h>
#include<ADXL345_WE.h> // https://wolles-elektronikkiste.de/adxl345-teil-1
#define ADXL345_I2CADDR 0x53
ADXL345_WE myAcc = ADXL345_WE(ADXL345_I2CADDR);
Adafruit_MCP23X17 mcp1;
Joystick_ Joystick(hidReportId, joystickType, buttonCount, hatSwitchCount, includeXAxis, includeYAxis, includeZAxis, includeRxAxis, includeRyAxis, includeRzAxis, includeRudder, includeThrottle, includeAccelerator, includeBrake, includeSteering);

bool reportpitch = false;

float throttle = 0;
int HSTPinA = 5;
int HSTPinB = 6;
Encoder myEnc(HSTPinA, HSTPinB); // RotaryEncoder 154 Steps

void setup() {
  pinMode(HSTPinA,INPUT_PULLUP);
  pinMode(HSTPinB,INPUT_PULLUP);
  pinMode(smoothPin,INPUT);
  Wire.begin();
  while(!myAcc.init()){
    Serial.println("ADXL345 not connected!");
    delay(1000);
  }
  if (report) Serial.println("ADXL345 connected...");

  myAcc.setCorrFactors(-266.0, 285.0, -268.0, 278.0, -291.0, 214.0);
  myAcc.setDataRate(ADXL345_DATA_RATE_50); // 50 Hz
  myAcc.setRange(ADXL345_RANGE_2G); // 2g

  if (!mcp1.begin_I2C()) {
    Serial.println("MCP23017 not connected!");
    while (1);
  } else
    if (report) Serial.println("MCP23017 connected");

  mcp1.begin_I2C(0x20); // Init MCP23017 at address 0x20
  Joystick.begin();
  Joystick.setRxAxisRange(0, 1023);
  Joystick.setRyAxisRange(0, 1023);
  Joystick.sendState();
  for (int i=0; i<10; i++) { // 10 Button & Switches
    mcp1.pinMode(i, INPUT_PULLUP);
  }
  if (report) Serial.println("los gehts...");
}

int lastButtonState[10] = {0,0,0,0,0,0,0,0,0,0};

void checkPitch() {
  xyzFloat corrAngles = myAcc.getCorrAngles();
  float pitch = ( (myAcc.getRoll()-90) /40 *1023);
  if(pitch<0) pitch=0;
  if(pitch>1023) pitch=1023;
  Filtern(sPitch,pitch,smooth);
  Joystick.setRxAxis(sPitch);
  if (reportpitch) {
    Serial.print("Pitch:");
    Serial.print(pitch);
    Serial.print(", ");
    Serial.print("sPitch:");
    Serial.print(sPitch);
    Serial.print(", ");
    reportpitch = false;
  }
}

void loop() {
  for (int i=0;i<10;i++) {
    bool currentButtonState = !mcp1.digitalRead(i);
    if (currentButtonState != lastButtonState[i]) {
      Joystick.setButton(i, currentButtonState);
      lastButtonState[i] = currentButtonState;
    }
  if ( myEnc.read() < 0 ) myEnc.write(0);
  if ( myEnc.read() > maxenccount ) myEnc.write(maxenccount);
  throttle = myEnc.read();
  Joystick.setRyAxis(throttle/maxenccount*1023);

    if (report) {
      if ( i == 9 )
        reportpitch = true;
      Serial.print("Btn");
      Serial.print(i);
      Serial.print(":");
      Serial.print(currentButtonState);
      Serial.print(", ");
    }
    checkPitch();
  }
  if (report) {
    Serial.print("Thr:");
    Serial.print(throttle/maxenccount*1023);
    Serial.println();
  }
}

Wieder was gelernt:

Serial.print

scheint ohne

Serial.begin

zu funktionieren.
Das wusste ich bisher nicht.

Nicht alles was man lernt, ist auch richtig. :stuck_out_tongue:

Beim Leonardo und (Pro) Micro ist das so, korrekt.

Ahso, damit hatte ich bisher noch nicht gearbeitet.
Danke für die Aufklärung.

Das soll doch wohl keine Kommazahl werden....

Aber viel schöner ist der hier:

Warum macht man sowas?
In jeder Zeile liefert Dir myEnc.read() einen anderen Wert.

Da passt vermutlich noch einiges nicht...

In dieser Zeile wird das aber:

Joystick.setRyAxis(throttle/maxenccount*1023);

Was ist dagegen einzuwenden? An A2 kommt ein Poti.

Warum? Doch nur, wenn er sich zwischenzeitlich ändert. Warum sollte er das? Es geht hier lediglich um die selbstkalibrierende Eingrenzung.
Da ja Schritte verloren werden, kommt man so durch drehen von min bis max und wieder zurück in sein nutzbares Fenster.

Was wird da? Du dividierst throttle/maxenccount Nicht mehr und nicht weniger. Erkläre mir, warum maxenccount float sein muss.
Davom abgesehen, das myEnc.read() bestimmt keinen float liefert und somit throttle eben auch nur ein (unsigned) int ist.
.setRyAxis erwartet einen int32_t
Nachzulesen in der joystick.cpp

Ich sehe also nirgendwo irgendwas mit float.

Das ist egal, was da ran kommt. A2 ist die PIN-Nummer. Im Arduino-Pinout wird aus A2 eine Ganzzahl.
Das kannst Du ausprobieren, indem Du einfach folgenden Sketch auf den arduino spielst und Dir die ausgabe auf dem SerMon anschaust:

void setup()
{
  Serial.begin(115200);
  Serial.println(A2);
}

void loop()
{
}

Weil er es kann!

Im Übrigen solltest Du die Zeit messen, die drei read() benötigen.
Dem gegenüber kannst Du dann den dreifachen Vergleich mit einmalig eingelesenen Variable anstellen.

Und egal wie Du es drehst. Du wirst nicht umhin kommen Deinen Code effizienter zu machen. Da gehört sowas wichtiges wie das begrenzen der Variablen auf die möglich geringste Verarbeitungsbreite der CPU dazu.