Controlling servos with a head tracker, how do I do that?

I dont know if im right here but here we go.

I want to use a Arduino nano 33 ble as a custom Headtracker to track the tilt and pan from my Head where it can control two servors for a Puppethead with tilt and pan movement.I tried finding Tutorials about this topic but there are all about connecting a Headtracker with a Radio, what i dont need.

Any help is much appreciated even if its just a link to a Tutorial and i hope you could unterstand my Problem with my level of Englisch.

Welcome to the forum

Start simple
Can you read the pan and tilt values from the Nano and print them on the Serial monitor ?

Yes you can with those commands.

#include <Arduino_LSM9DS1.h>

float x, y, z;
int X = 0;
int Y = 0;

void setup() {
  Serial.begin(9600);
  while (!Serial);
  Serial.println("Started");

  if (!IMU.begin()) {
    Serial.println("Failed to initialize IMU!");
    while (1);
  }

  Serial.print("Accelerometer sample rate = ");
  Serial.print(IMU.accelerationSampleRate());
  Serial.println("Hz");
}

void loop() {

  if (IMU.accelerationAvailable()) {
    IMU.readAcceleration(x, y, z);

  }

  if (x > 0.1) {
    x = 100 * x;
    X = map(x, 0, 97, 0, 90);
    Serial.print("Tilting up ");
    Serial.print(X);
    Serial.println("  degrees");
  }
  if (x < -0.1) {
    x = 100 * x;
    X = map(x, 0, -100, 0, 90);
    Serial.print("Tilting down ");
    Serial.print(X);
    Serial.println("  degrees");
  }
  if (y > 0.1) {
    y = 100 * y;
    Y = map(y, 0, 97, 0, 90);
    Serial.print("Tilting left ");
    Serial.print(Y);
    Serial.println("  degrees");
  }
  if (y < -0.1) {
    y = 100 * y;
    Y = map(y, 0, -100, 0, 90);
    Serial.print("Tilting right ");
    Serial.print(Y);
    Serial.println("  degrees");
  }
  delay(1000);
}

could you then use the variables for the Servos like that? Also i dont really understand how the map works.Is the map just the range where it can read?

servox.write(X);
servoy.write(Y);

The map() function takes a value in a range and converts it to the equivalent number in another range

So, if the x value was in the range 0 to 1000 and it was currently 500 you would want to move the servo to an angle of 90 to drive the servo to its centre position so you would map() the x value like this

int servoAngle = map(x, 0, 1000, 0, 180);

In other words, given an x value between 0 and 1000 return a proportional value between 0 and 180 That is all there is to it. I only used 0 to 100 as an example. What range of values for x do you get in practice ?

See map() - Arduino Reference

The code you posted uses a very poor approximation to estimate tilt angles. To measure them accurately is much simpler using this method: How_to_Use_a_Three-Axis_Accelerometer_for_Tilt_Sensing-DFRobot

I have this ranges

int x = map(x, 0, 360, 0, 180);
int y = map(y, -88, -88, 0, 180);
int z = map(z, -176, 176, 0, 180);

i did it now like that

#include <Arduino_LSM9DS1.h>
#include "MadgwickAHRS.h"
#include <Servo.h>

Servo myservoyaw;
Servo myservopitch;
Servo myservoroll;

int x = map(x, 0, 360, 0, 180);
int y = map(y, -88, -88, 0, 180);
int z = map(z, -176, 176, 0, 180);
// initialize a Madgwick filter:
Madgwick filter;
// sensor's sample rate is fixed at 104 Hz:
const float sensorRate = 104.00;

void setup() {
  Serial.begin(9600);
  // attempt to start the IMU:
  if (!IMU.begin()) {
    Serial.println("Failed to initialize IMU");
    // stop here if you can't access the IMU:
    while (true);
  }
  // start the filter to run at the sample rate:
  filter.begin(sensorRate);
  myservoyaw.attach(D9);
  myservopitch.attach(D8);
 myservoroll.attach(D7);
}

void loop() {
  // values for acceleration and rotation:
  float xAcc, yAcc, zAcc;
  float xGyro, yGyro, zGyro;

  // values for orientation:
  float roll, pitch, heading;
  // check if the IMU is ready to read:
  if (IMU.accelerationAvailable() &&
      IMU.gyroscopeAvailable()) {
    // read accelerometer &and gyrometer:
    IMU.readAcceleration(xAcc, yAcc, zAcc);
    IMU.readGyroscope(xGyro, yGyro, zGyro);

    // update the filter, which computes orientation:
    filter.updateIMU(xGyro, yGyro, zGyro, xAcc, yAcc, zAcc);

    // print the heading, pitch and roll
    roll = filter.getRoll();
    pitch = filter.getPitch();
    heading = filter.getYaw();
    Serial.print("Orientation: ");
    Serial.print(heading);
    Serial.print(" ");
    Serial.print(pitch);
    Serial.print(" ");
    Serial.println(roll);
    myservoyaw.write(x); 
    myservopitch.write(y); 
    myservoroll.write(z); 
  }
}

Also it seems i cant control the servo even with the example Sweep code.

Fix the problem with Sweep first, then you will know that the servo works

What happens when you run Sweep ?
Which pin is the servo connected to ?
Have you got the right pin coded into Sweep ?
How is the servo powered ?

The Code for the Orientation is working i get yaw,pitch,roll angel so the board is okay i assume.I also checked the servo with a arduino uno and it is working.
I run it and the servo doesnt move.
The servo is connected to pin D8.
The servo is powered 5v extern.
Yes i have the liabry for the nano 33 ble and using it.


#include <Servo.h>

Servo myservo; 

int pos = 0;  

void setup() {
  myservo.attach(D8);  
}

void loop() {
  for (pos = 0; pos <= 180; pos += 1) {

    myservo.write(pos);              
    delay(15);                       
  }
  for (pos = 180; pos >= 0; pos -= 1) { 
    myservo.write(pos);              
    delay(15);
  }
}

I found the problem the line from the extern power was kaput, now its working
.

if i put in the code

   myservoyaw.write(x); 
    myservopitch.write(y); 
    myservoroll.write(z); 

the button port for the nano 33ble is greyed out why is that?

  myservo.attach(D8);  // attaches the servo on pin 9 to the servo object

Please make your mind up which pin you are using ?

The point is that the comment doesn't match. I'd suggest that you delete it - it doesn't tell you anything you can't get from reading the code.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.